/* 关键卡在求前4位,参考了网上的 对于很大的数,要很容易想到log10 我们要搬出Fibonacci的通项公式—— f(n)=1/sqrt(5)(((1+sqrt(5))/2)^n+((1-sqrt(5))/2)^n) 假设F[n]可以表示成 t * 10^k(t是一个小数),那么对于F[n]取对数log10,答案就为log10 t + K, 此时很明显log10 t<1,于是我们去除整数部分,就得到了log10 t ,再用pow(10,log10 t)我们就还原回了t。 将t×1000就得到了F[n]的前四位。具体实现的时候Log10 F[n]约等于((1+sqrt(5))/2)^n/sqrt(5), 这里我们把((1-sqrt(5))/2)^n这一项忽略了,因为当N>=40时,这个数已经小的可以忽略。 于是log10 F[n]就可以化简成log10 1/sqrt(5) + n*log10 (1+sqrt(5))/2 */ #include <iostream> #include <cstdio> #include <cmath> #define aa ((1 + sqrt(5.0))/2) using namespace std; int Fic[41] = {0, 1, 1}; const int mod = 10000; struct Mat { int num[2][2]; Mat () { for(int i = 0; i < 2; i++) for(int j = 0; j < 2; j++) num[i][j] = 0; } } ; Mat init,unit; Mat mul(Mat a, Mat b) { Mat r; for(int i = 0; i < 2; i++) for(int k = 0; k < 2; k++) { if(a.num[i][k] == 0) continue; for(int j = 0; j < 2; j++) { if(b.num[k][j] == 0) continue; r.num[i][j] += a.num[i][k] * b.num[k][j]; if(r.num[i][j] >= mod) r.num[i][j] %= mod; } } return r; } Mat mal(int n) { while(n) { if(n & 1) { unit = mul(unit, init); n--; } else { init = mul(init, init); n >>= 1;//这里写成n >>= 2 一直悲剧 } } return unit; } int main() { int n; for(int i = 3; i < 40; i++) Fic[i] = Fic[i- 1] + Fic[i - 2]; while(scanf("%d", &n) != EOF) { if(n < 40) { printf("%d/n", Fic[n]); continue; } for(int i = 0; i < 2; i++) for(int j = 0; j < 2; j++) { init.num[i][j] = 1; unit.num[i][j] = 0;//这里注意初始话,unit是全局变量 } unit.num[0][1] = 1; init.num[0][0] = 0; Mat ans; ans = mal(n); double sum; sum = log10 (1 / sqrt(5.0)) + n * log10(aa);//((1 + sqrt(5.0))/ 2); sum -= (int)sum; sum = pow(10.0, sum); while(sum < 1000) sum *= 10; printf("%d...%04d/n", (int)sum, ans.num[0][0]);//没有%04d输出就是wong } }