如果用递归方式的话时很慢的,需要压栈,不停的调用很费时间,完全不建议。
代码:
#include <cstdio> #include<iostream> using namespace std; int f(long long n) { if(n <= 1)return n; return (f(n - 1) + f(n - 2)) % 10000; } int main() { long long n; cin>>n; cout<<f(n); }
也可以用循环,会快些,O(n)的时间,效率还是太低。
代码:
#include <cstdio> #include<iostream> using namespace std; int f(long long n) { if(n <= 1)return n; int a = 0,b = 1,c; long long i = 2; while(i <= n) { c = (a + b) % 10000; a = b; b = c; i ++; } return c; } int main() { long long n; cin>>n; cout<<f(n); }
斐波那契数列有通项公式,Fn = 1/根5 * (((1 + 根5) / 2)^n - ((1 - 根5) / 2)^n),但是有无理数,无法简单的求得取模后的结果。其实不用求出通项。
可以用矩阵解决。
Fn = Fn-1 + Fn-2,
Fn+1 = Fn + Fn-1,
(Fn+1 Fn)T = A(Fn Fn-1)T,
A =
(Fn+1 Fn)T = A^n(F1 F0)T,
只需要求出矩阵A的n次方之后,把结果矩阵再跟(1 0)T相乘就得出答案。
代码:
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; void mul(int (*a)[2],int (*b)[2]) { int d[2][2] = {0}; for(int i = 0;i < 2;i ++) { for(int j = 0;j < 2;j ++) { for(int k = 0;k < 2;k ++) { d[i][j] += (a[i][k] * b[k][j]) % 10000; } d[i][j] %= 10000; } } for(int i = 0;i < 2;i ++) { for(int j = 0;j < 2;j ++) { a[i][j] = d[i][j]; } } } int f(long long n) { int a[2][2] = {1,1,1,0},d[2][2] = {1,0,0,1}; while(n) { if(n % 2)mul(d,a); n /= 2; mul(a,a); } return d[1][0]; } int main() { long long n; cin>>n; cout<<f(n); }