前几天在我们学校的OJ平台上做了一道大数运算的题目,其实也不算很难,一次就通过了,不过还是想用日志记录一下解题思路。 先附上题目的链接How many Fibs?。这个题目的意思是,输入两个数a和b(a<=b<=10^100),计算a和b之间斐波那契数的个数(包含a和b,即若a或b也是斐波那契数的话,也计算在内)。 斐波那契数的计算我们都很熟悉,使用 这里有一个小技巧,感觉可以节省一些时间:首先把10^100以内的斐波那契数都计算出来,存放到数组中,当输入数据时,直接在数组中寻找开始和结束的位置,然后就能计算出中间的个数。不用每次输入a和b都重新递归一遍。那数组应该开多大比较合适呢,经过计算后,发现10^100以内的斐波那契数没有超过480个,因此用来存储数据的数组开到480就可以了。其实从这里,我们也能看到斐波那契数增长的恐怖程度了,还没到480个数,就已经差不多是个100位的数字了。 下面是是用 上面也说了,现在data数组中存储的斐波那契数都是倒着的,那输入a和b时怎么比较呢。我们仅仅是在计算斐波那契数的递归过程中没有颠倒,待计算全部完后就可以把data中存储的数据反过来了。 用一个循环就能把data数组中所有的斐波那契数都颠倒过来。 可是,在C语言中,使用 这样就能判断出边界了。递归
的方法就可以。 从给出的输入范围我们就能知道,这肯定是个大数运算了,10^100的数据,即时是使用double
和__int64
的类型都存不下的。对于这种大数运算,只能采用字符串进行模拟了。递归
和字符串
计算斐波那契数的递归过程,不过下面计算出的斐波那契数都是倒着的,大数计算就是模拟我们人类计算两个数的和的过程,先计算个位,若超过10就向高位进1,一直到最后;因为要计算很多的数,因此没有在递归的过程中,把斐波那契数反过来;因为即使反过来,下次再使用时还要再反回去:char data[485][110]; // 存储斐波那契数,每项默认是"0"
// 计算第k个斐波那契数,用s返回
void fb(int k, char *s){
// 若数组中已经存在斐波那契数,直接返回
if(strcmp(data[k], "0")!=0){
strcpy(s, data[k]);
return;
}
char x[110], y[110], result[110];
int c, i, j, n, m, t1, t2, min, max1, max2;
// 递归计算出第k-2和第k-1的斐波那契数x, y
fb(k-2, x);
fb(k-1, y);
// 计算x, y的长度
t1 = strlen(x);
t2 = strlen(y);
min = t1
void reverse(char *s){
int i, t, tt;
char temp;
t = strlen(s);
tt = t/2;
for(i=0; i-1-i];
s[t-1-i] = temp;
}
}
strcpm
进行字符串比较时,"2"是比"100"要大的,因为当开始进行字符串比较时,首先比较比较第一个字符,若第1个字符大,就表示这整个字符串大,若第一个字符是相等的,才开始比较第二个,一直比较到最后。因此,我这里用了两个条件进行判断:
while(scanf("%s %s", a, b)){
if(strcmp(a, "0")==0 && strcmp(b, "0")==0){
break;
}
start = len, end = 0;
ed = 0;
at = strlen(a);
bt = strlen(b);
for(i=0; i
版权属于:
加速器之家
作品采用:
《
署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)
》许可协议授权
评论