The close form of fibs does not help in the problem. The input range is too large that the precision of long double won't be sufficient to handle it correctly. Just generate all the fibs up to 100 digits and use string compare to find the bounds.
Code:
- #include <algorithm>
- #include <cmath>
- #include <cstdio>
- #include <cstring>
- #include <deque>
- #include <fstream>
- #include <iostream>
- #include <list>
- #include <map>
- #include <queue>
- #include <set>
- #include <stack>
- #include <string>
- #include <vector>
- using namespace std;
- struct bignum
- {
- bignum(int v = 0) : start(max_digits)
- {
- bzero(digits, max_digits);
- assign(v);
- }
- bignum(char const *v) : start(max_digits)
- {
- bzero(digits, max_digits);
- assign(v);
- }
- void assign(int v)
- {
- start = max_digits;
- for (; v != 0; v /= 10) digits[--start] = v % 10;
- }
- void assign(char const *v)
- {
- start = max_digits - strlen(v);
- for (int i = start; i < max_digits; ++i)
- digits[i] = *v++ - '0';
- remove_leading_zero();
- }
- void convert(int& v) const
- {
- v = 0;
- for (int i = start; i < max_digits; ++i, v *= 10) v += digits[i];
- }
- void convert(char *v) const
- {
- for (int i = start; i < max_digits; ++i)
- *v++ = digits[i] + '0';
- *v = '/0';
- }
- bignum& operator+=(bignum const& other)
- {
- start = min(start, other.start) - 1;
- for (int i = max_digits - 1, carry = 0; i >= start; --i) {
- int s = digits[i] + other.digits[i] + carry;
- digits[i] = s % 10;
- carry = s / 10;
- }
- remove_leading_zero();
- return *this;
- }
- bignum operator+(bignum const& other) const
- {
- bignum tmp(*this);
- tmp += other;
- return tmp;
- }
- bool operator<(bignum const& other) const
- {
- if (start > other.start) return true;
- else if (start < other.start) return false;
- return memcmp(digits + start, other.digits + start, max_digits - start) < 0;
- }
- static int const max_digits = 500;
- char digits[max_digits];
- int start;
- private:
- void remove_leading_zero()
- {
- for (; digits[start] == 0 && start < max_digits; ++start) {}
- }
- };
- inline istream& operator>>(istream& is, bignum& n)
- {
- char buf[bignum::max_digits+1];
- is >> buf;
- n.assign(buf);
- return is;
- }
- inline ostream& operator<<(ostream& os, bignum const& n)
- {
- char buf[bignum::max_digits+1];
- n.convert(buf);
- os << buf;
- return os;
- }
- void gen_fibs(bignum *fibs, int nfibs)
- {
- fibs[0] = 1;
- fibs[1] = 2;
- for (int i = 2; i < nfibs; ++i)
- fibs[i] = fibs[i-1] + fibs[i-2];
- }
- int main(int argc, char *argv[])
- {
- #ifndef ONLINE_JUDGE
- freopen((string(argv[0]) + ".in").c_str(), "r", stdin);
- freopen((string(argv[0]) + ".out").c_str(), "w", stdout);
- #endif
- int const nfibs = 500;
- bignum fibs[nfibs];
- gen_fibs(fibs, nfibs);
- for (string s1, s2; cin >> s1 >> s2 && !(s1 == "0" && s2 == "0"); ) {
- bignum a(s1.c_str()), b(s2.c_str());
- int count;
- if (b < a) {
- count = 0;
- } else {
- bignum *first = lower_bound(fibs, fibs + nfibs, a);
- bignum *last = upper_bound(fibs, fibs + nfibs, b);
- count = last - first;
- }
- cout << count << '/n';
- }
- return 0;
- }