Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 9442 Accepted Submission(s): 3096
Problem Description
A Fibonacci sequence is calculated by adding the previous two members the sequence, with the first two members being both 1.
F(1) = 1, F(2) = 1, F(3) = 1,F(4) = 1, F(n>4) = F(n - 1) + F(n-2) + F(n-3) + F(n-4)
Your task is to take a number as input, and print that Fibonacci number.
Input
Each line will contain an integers. Process to end of file.
Output
For each case, output the result in a line.
Sample Input
Sample Output
4203968145672990846840663646 Note: No generated Fibonacci number in excess of 2005 digits will be in the test data, ie. F(20) = 66526 has 5 digits.
Author
戴帽子的
题解,同一般的斐波那契数列来说,最先的我想到了用大数加法和快速幂矩阵的方法来做,但是由于大数乘法的模板是O(n^2)所以超时了,所以考虑只用大数加法的直接暴力方法,由于斐波那契数列增长很快,所以位数不超过2005的前提下最多n 不超过10000,然后就过了, 希望看到的大神吗也可以帮我提供一个复杂度小的大数乘法的模板,万分感激
下面给出ac代码,和用矩阵快速幂tle的代码:
ac代码:
1 #include <iostream> 2 #include<cstdio> 3 #include<string> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 string add(string s1,string s2) 8 { 9 string ans = ""; 10 int i,j,x,y,k=0; 11 for(i=s1.length()-1,j=s2.length()-1;i>=0 && j>=0 ;i--,j--) 12 { 13 x = s1[i] - '0'; 14 y = s2[j] - '0'; 15 ans += char((x+y+k)%10 + '0'); 16 k = (x+y+k)/10; 17 } 18 while(i>=0) 19 { 20 x=s1[i]-'0'; 21 ans += char ((x+k)%10 + '0'); 22 k = (x+k)/10; 23 i--; 24 } 25 while(j>=0) 26 { 27 y=s2[j]-'0'; 28 ans += char((y+k)%10 + '0'); 29 k = (y+k)/10; 30 j--; 31 } 32 if(k>0) 33 ans += '1'; 34 //ans.reverse(); 35 reverse(ans.begin(),ans.end()); 36 return ans; 37 } 38 string ms1, ms2, ms3, ms4, ms; 39 int main() 40 { 41 int n; 42 while(~scanf("%d",&n)) 43 { 44 ms1 = ms2 = ms3 = ms4 = "1"; 45 if(n <= 4) {puts("1"); continue;} 46 for(int i = 0; i < n-4; i++) 47 { 48 ms = add(ms1, ms2); 49 ms = add(ms, ms3); 50 ms = add(ms, ms4); 51 ms1 = ms2; 52 ms2 = ms3; 53 ms3 = ms4; 54 ms4 = ms; 55 } 56 cout << ms << endl; 57 } 58 return 0; 59 }
矩阵快速幂tle代码:
1 #include <iostream> 2 #include<cstdio> 3 #include<string> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 string add(string s1,string s2) 8 { 9 string ans = ""; 10 int i,j,x,y,k=0; 11 for(i=s1.length()-1,j=s2.length()-1;i>=0 && j>=0 ;i--,j--) 12 { 13 x = s1[i] - '0'; 14 y = s2[j] - '0'; 15 ans += char((x+y+k)%10 + '0'); 16 k = (x+y+k)/10; 17 } 18 while(i>=0) 19 { 20 x=s1[i]-'0'; 21 ans += char ((x+k)%10 + '0'); 22 k = (x+k)/10; 23 i--; 24 } 25 while(j>=0) 26 { 27 y=s2[j]-'0'; 28 ans += char((y+k)%10 + '0'); 29 k = (y+k)/10; 30 j--; 31 } 32 if(k>0) 33 ans += '1'; 34 //ans.reverse(); 35 reverse(ans.begin(),ans.end()); 36 return ans; 37 } 38 string mul(string s1,string s2) 39 { 40 string ans = ""; 41 int c = 0; 42 for(int i = s1.length()-1; i >= 0; i--) 43 { 44 //计算s1[i]*s2,结果保存在tem中 45 string tem = ""; 46 int x = s1[i] - '0',k = 0;//乘数和初始余数 47 for(int j = s2.length()-1; j >= 0; j--) 48 { 49 int y = s2[j] - '0'; 50 int d = x*y+k; 51 tem = char(d%10 + '0') + tem; 52 k = d/10; 53 } 54 if(k) 55 tem = char(k+'0') + tem; 56 for(int h = 0; h < c; h++) 57 tem = tem+'0'; 58 c++; 59 //tem计算完毕 60 ans = add(ans,tem); 61 } 62 return ans; 63 } 64 struct mlt{ 65 string a1,a2,a3,a4,b1,b2,b3,b4,c1,c2,c3,c4,d1,d2,d3,d4; 66 void out (){ 67 printf("%s %s %s %s/n", a1.c_str(), a2.c_str(), a3.c_str(), a4.c_str()); 68 printf("%s %s %s %s/n", b1.c_str(), b2.c_str(), b3.c_str(), b4.c_str()); 69 printf("%s %s %s %s/n", c1.c_str(), c2.c_str(), c3.c_str(), c4.c_str()); 70 printf("%s %s %s %s/n", d1.c_str(), d2.c_str(), d3.c_str(), d4.c_str()); 71 } 72 mlt operator * (const mlt m) const 73 { 74 mlt tm; 75 tm.a1 = add(add(add(mul(a1,m.a1),mul(a2,m.b1)),mul(a3,m.c1)),mul(a4,m.d1)); 76 tm.a2 = add(add(add(mul(a1,m.a2),mul(a2,m.b2)),mul(a3,m.c2)),mul(a4,m.d2)); 77 tm.a3 = add(add(add(mul(a1,m.a3),mul(a2,m.b3)),mul(a3,m.c3)),mul(a4,m.d3)); 78 tm.a4 = add(add(add(mul(a1,m.a4),mul(a2,m.b4)),mul(a3,m.c4)),mul(a4,m.d4)); 79 tm.b1 = add(add(add(mul(b1,m.a1),mul(b2,m.b1)),mul(b3,m.c1)),mul(b4,m.d1)); 80 tm.b2 = add(add(add(mul(b1,m.a2),mul(b2,m.b2)),mul(b3,m.c2)),mul(b4,m.d2)); 81 tm.b3 = add(add(add(mul(b1,m.a3),mul(b2,m.b3)),mul(b3,m.c3)),mul(b4,m.d3)); 82 tm.b4 = add(add(add(mul(b1,m.a4),mul(b2,m.b4)),mul(b3,m.c4)),mul(b4,m.d4)); 83 tm.c1 = add(add(add(mul(c1,m.a1),mul(c2,m.b1)),mul(c3,m.c1)),mul(c4,m.d1)); 84 tm.c2 = add(add(add(mul(c1,m.a2),mul(c2,m.b2)),mul(c3,m.c2)),mul(c4,m.d2)); 85 tm.c3 = add(add(add(mul(c1,m.a3),mul(c2,m.b3)),mul(c3,m.c3)),mul(c4,m.d3)); 86 tm.c4 = add(add(add(mul(c1,m.a4),mul(c2,m.b4)),mul(c3,m.c4)),mul(c4,m.d4)); 87 tm.d1 = add(add(add(mul(d1,m.a1),mul(d2,m.b1)),mul(d3,m.c1)),mul(d4,m.d1)); 88 tm.d2 = add(add(add(mul(d1,m.a2),mul(d2,m.b2)),mul(d3,m.c2)),mul(d4,m.d2)); 89 tm.d3 = add(add(add(mul(d1,m.a3),mul(d2,m.b3)),mul(d3,m.c3)),mul(d4,m.d3)); 90 tm.d4 = add(add(add(mul(d1,m.a4),mul(d2,m.b4)),mul(d3,m.c4)),mul(d4,m.d4)); 91 return tm; 92 } 93 }; 94 string qkmul(int n) 95 { 96 mlt flag; 97 flag.a1 = flag.a2 = flag.a3 = flag.a4 = flag.b1 = flag.c2 = flag.d3 ="1"; 98 flag.b2 = flag.b3 = flag.b4 = flag.c1 = flag.c3 = flag.c4 = flag.d1 = flag.d2 = flag.d4 = "0" ; 99 n = n-4; 100 mlt ret; ret.a1 = ret.b2 = ret.c3 = ret.d4 = "1"; 101 ret.a2 = ret.a3 = ret.a4 = ret.b1 = ret.b3 = ret.b4 = ret.c1 = ret.c2 = ret.c4 = ret.d1 = ret.d2 = ret.d3 = "0"; 102 while(n!=0) 103 { 104 if(n%2==1) 105 ret = ret*flag; 106 n/=2; 107 flag = flag*flag; 108 } 109 //flag.out(); 110 flag = ret; 111 string ss = ""; 112 ss = add(add(add(flag.a1,flag.a2),flag.a3),flag.a4); 113 return ss; 114 } 115 116 int main() 117 { 118 int n; 119 while(~scanf("%d",&n)) 120 { 121 string sss = qkmul(n); 122 cout<<sss<<endl; 123 } 124 return 0; 125 }
注明: 一般的斐波那契在n不是很大的情况可以直接用暴力的方法就可以解决了。