您的位置:首页 > 其它

Sicily E1_fib1 斐波那契数列取模(大数)分治算法

2014-09-26 22:59 381 查看


思路与源代码参考地址在此



(1)由于有如下性质:

(n*m)%c=[(n%c)*(m%c)]%c

(n+m)%c=[(n%c)+(m%c)]%c ,

计算过程中可以随时取模,而不影响最终的结果。

(2)利用矩阵求斐波那契数列:

(3)

二分的原理:要求矩阵的N次方A(N),设i=N/2。若N%2==1, 则 A(N)=A(i)*A(i)*A(1);若N%2==0, 则 A(N)=A(i)*A(i)

基于二进制的原理:将N拆为二进制数,譬如13=1101那么 A^13= A^8 * A^4 * A^1 (这里^表示幂运算)

也就是说,由A^1开始,自乘得到A^2,然后自乘得到A^4,如果N对应位为1,则将这个结果乘到目标上去

这样的话,将所有乘法改为模乘,就可以得到一个较大Fibonacci数除以M的余数

实现代码:

#include<iostream>
using namespace std;

#define mod 1000000007
// f(n)=f(i)*f(n-i-1)+f(i+1)*f(n-i)
int tempA, tempB, tempC, tempD;
void func(int n, int &a, int &b, int &c, int &d){
if (n == 1){
a = 0;
b = c = d = 1;
return;
}
if (n % 2 == 0){
func(n / 2, a, b, c, d);
tempA = a*a + b*c;
tempB = b*(a + d);
tempC = c*(a + d);
tempD = c*b + d*d;
a = tempA % mod;
b = tempB % mod;
c = tempC % mod;
d = tempD % mod;
return;
}
else{
func(n / 2, a, b, c, d);
tempA = b*(a + d);
tempB = a*a + b*(a + c + d);
tempC = c*b + d*d;
tempD = c*(a + b + d) + d*d;
a = tempA % mod;
b = tempB % mod;
c = tempC % mod;
d = tempD % mod;
return;
}
}
int main(){
int n;
while (cin >> n&&n != 0){
int a, b, c, d;
if (n <= 2){
cout << 1 << endl;
continue;
}
else n -= 2;
func(n, a, b, c, d);
cout << (b + d) % mod << endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: