/* *State: 3117 0MS 424K 1028 B C++ *题目大意: * 求出第nth个fib数,要求大于8位的只输出前4位跟后4位。 *解题思路: * 后四位可以用矩阵快速幂来求,但是根据模的特性,发现原来 * 周期15000fib又会回来。所以可以用数组来保存这个循环节即可。 * 而前四位可以用log10.来计算,原来就是每一个数都可以用科学 * 计数法来表示,我们用log10来取出每一个数科学计数法的那几个 * 决定位权数的值,然后要n位就乘以10^n.不过要注意精度问题哦。 */
View Code
1 #include <iostream> 2 #include <cmath> 3 using namespace std; 4 5 const int MAX = 16000; 6 int mod = 10000; 7 int fiblast[MAX] = {0, 1, 1}, fib[MAX] = {0, 1, 1}; 8 double N1 = (1.0 + sqrt(5.0)) / 2.0; 9 10 void pre_init() 11 { 12 for(int i = 3; i < MAX; i++) 13 { 14 fiblast[i] = (fiblast[i - 1] + fiblast[i - 2]) % mod; 15 if(fiblast[i] == fiblast[1] && fiblast[i - 1] == fiblast[0]) 16 break; 17 fib[i] = fib[i - 1] + fib[i - 2]; 18 } 19 return ; 20 } 21 22 int main(void) 23 { 24 #ifndef ONLINE_JUDGE 25 //freopen("in.txt", "r", stdin); 26 #endif 27 pre_init(); 28 int n; 29 while(scanf("%d", &n) == 1) 30 { 31 if(n < 40) 32 { 33 printf("%d\n", fib[n]); 34 continue; 35 } 36 double k = log10(1.0/sqrt(5.0)) + (double)n * log10(N1); 37 //((1-sqrt(5)) / 2)^n当n==40的时候已经小数点后10位了, 38 //可以忽略,本题不要求那么高的精度 39 double tmp = k; 40 tmp = k - (int)tmp; 41 printf("%d...%0.4d\n", (int)(1000.0 * pow(10.0, tmp)), fiblast[n % 15000]); 42 } 43 return 0; 44 }