您的位置:首页 > 其它

uva 10183 how many fibs

2011-10-03 16:28 381 查看

Problem B: How many Fibs?

Recall the definition of the Fibonacci numbers:

f1 := 1

f2 := 2

fn := fn-1 + fn-2 (n>=3)
Given two numbers a and b, calculate how many Fibonacci numbers are in the range [a,b].
Input Specification

The input contains several test cases. Each test case consists of two non-negative integer numbers a and b. Input is terminated bya=b=0. Otherwise, a<=b<=10100. The numbers a and b are given
with no superfluous leading zeros.

Output Specification

For each test case output on a single line the number of Fibonacci numbers fi with a<=fi<=b.

Sample Input

10 100
1234567890 9876543210
0 0

Sample Output

5
4


一开始用 double 代 fabonacci 公式: 1 / 根5 * (((1 + 根5) / 2) ^ n - ((1 + 根5) / 2) ^ n),用二分法求起止项号,并用项号相减,WA,原因是 double 精度不够。

后来发现第400多项就可以达到 10 的 100 次方,只要预先计算这 400 多项,然后每读入一组数据暴力枚举即可,不需要二分法如此复杂,不过需要写一下高精度加法。

WA代码

#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <cmath>
#include <algorithm>

const double esp = 1e-5;

double fib (double i) {
static double sqrt5 = sqrt (5.0);
return 1.0 / sqrt5 * (pow ((1.0 + sqrt5) / 2, i) - pow ((1.0 - sqrt5) / 2, i));
}

long long bin (double f) {
long long hi = 1;
while (fib (hi) < f) {
hi *= 2;
}
if (hi < 2) {
return hi;
}
long long lo = hi / 2;
double fib_lo = fib (lo);
double fib_hi = fib (hi);
double t = (fib_lo - f) * (fib_hi - f);
while (lo < hi && (t < 0 || fabs (t) < esp)) {
long long mid = (lo + hi) >> 1;
double fib_mid = fib (mid);
t = (fib_lo - f) * (fib_mid - f);
if (t < 0.0 || fabs (t) < esp) {
hi = mid;
fib_hi = fib_mid;
} else {
lo = mid + 1;
fib_lo = fib (mid + 1);
t = (fib_lo - f) * (fib_hi - f);
}
}
return lo;
}

int main () {
double a, b;
while (scanf ("%lf%lf", &a, &b) == 2 && (fabs (a) > esp || fabs (b) > esp)) {
long long ia = bin (a);
long long ib = bin (b);
ia = std::max (2LL, ia);
ib = std::max (2LL, ib);
#ifdef _DEBUG
printf ("ia = %lld, ib = %lld\n", ia, ib);
#endif
if (fabs (fib (ib) - b) < esp) {
printf ("%lld\n", ib - ia + 1);
} else {
printf ("%lld\n", ib - ia);
}
}
return 0;
}


AC代码

#include <cstdio>
#include <cassert>
#include <cstdlib>
#include <cstring>

#define FIBS_MAX 500
#define DIGS_MAX 110

int fib [FIBS_MAX][DIGS_MAX];

void Add (int *a, int *b) {
int car = 0;
for (int i=0; i<DIGS_MAX; ++i) {
int t = a[i] + b[i] + car;
car = t / 10;
a[i] = t % 10;
}
assert (car == 0);
}

void InitFibs () {
memset (fib, 0, sizeof (fib));
fib[1][0] = 1;
fib[2][0] = 2;
for (int i=3; i<FIBS_MAX; ++i) {
Add (fib[i], fib[i - 1]);
Add (fib[i], fib[i - 2]);
}
}

bool IsLess (int *a, int *b) {
for (int i=DIGS_MAX-1; i>=0; --i) {
if (a[i] < b[i]) {
return true;
} else if (a[i] > b[i]) {
return false;
}
}
return false;
}

void GetInt (int *a) {
static char s[1024];
if (scanf ("%s", s) == EOF) {
exit (0);
}
char *p = s + strlen (s);
memset (a, 0, sizeof (*a) * DIGS_MAX);
do {
*a++ = *--p - '0';
} while (p > s);
}

bool IsZero (int *a) {
for (int i=0; i<DIGS_MAX; ++i) {
if (a[i]) {
return false;
}
}
return true;
}

void Solve () {
int a[DIGS_MAX];
int b[DIGS_MAX];
GetInt (a);
GetInt (b);
if (IsZero (a) && IsZero (b)) {
exit (0);
}
int i = 0;
while (++i < FIBS_MAX && IsLess (fib[i], a)) {}
int k = 0;
while (++k < FIBS_MAX && IsLess (fib[k], b)) {}
assert (i < FIBS_MAX && k < FIBS_MAX && k >= i);
if (! IsLess (b, fib[k])) {
printf ("%d\n", k - i + 1);
} else {
printf ("%d\n", k - i);
}
}

int main () {
InitFibs ();
while (true) {
Solve ();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: