HDU4549M-斐波那契数列(矩阵快速幂,二分幂)
来源:互联网 发布:phpstorm apache 编辑:程序博客网 时间:2024/06/06 15:48
M斐波那契数列
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 519 Accepted Submission(s): 145
F[0] = a
F[1] = b
F[n] = F[n-1] * F[n-2] ( n > 1 )
现在给出a, b, n,你能求出F[n]的值吗?
每组数据占一行,包含3个整数a, b, n( 0 <= a, b, n <= 10^9 )
0 1 06 10 2
060
分析:我们写出该数列的前几项:a, b, ab, ab^2, a^2*b^3, a^3*b^5。。。。我们可以发现,F(n)=a^f(n)*b^f(n-1),这里f(n)是斐波那契数列(f(0)=0,f(1)=1,f(2)=1,f(n)=f(n-1)+f(n-2)),所以,我们可以先用矩阵快速幂算出f(n)和f(n-1),然后再用二分快速求幂计算出F(n)。但是,我们会发现一个问题,如果n很大的话,则f(n)太大,无法表示。所以我们想到了费马小定理,描述如下:如果a和p互素,那么a^(p-1)mod p=1。所以,我们要可以用费马小定理对a^f(n)中指数f(n)缩减为F(n)=a^(f(n)%M) * b^(f(n-1)% M),其中M=p-1,在这里,M=1000000007-1。
#include<stdio.h>#include<string.h>#define M 1000000007void fun(__int64 a[][2],__int64 b[][2]){ __int64 c[2][2]={0},i,j,k; for(i=0;i<2;i++){ for(j=0;j<2;j++){ for(k=0;k<2;k++){ c[i][j]+=a[i][k]*b[k][j]; c[i][j]%=(M-1); } } } for(i=0;i<2;i++){ for(j=0;j<2;j++){ a[i][j]=c[i][j]; } }}__int64 getx(__int64 x, __int64 y){ __int64 sum=1; while(y>0){ if(y&1) sum=sum*x%M; x=x*x%M; y=y/2; } return sum;}int main(){ __int64 x,y,n,a[2][2],b[2][2],t,sum; while(scanf("%I64d %I64d %I64d",&x,&y,&n)!=EOF){if(n==0){printf("%I64d\n",x%M);continue;}else if(n==1){printf("%I64d\n",y%M);continue;} a[0][0]=1,a[0][1]=1,a[1][0]=1,a[1][1]=0; b[0][0]=1,b[0][1]=0,b[1][0]=0,b[1][1]=1; t=n; while(t>0){ if(t&1) fun(b,a); fun(a,a); t=t/2; } sum=getx(x,b[1][1])*getx(y,b[1][0])%M; printf("%I64d\n",sum); } return 0;}
对于以上计算斐波那契的过程,我们可以如下结论:我们定义f(0)=a,f(1)=b,f(2)=a+b...f(n)=f(n-1)+f(n-2),这样,我么也可以通过矩阵快速幂迅速求得 f(n)矩阵连乘为 A*B^(n-1),其中 A 为初始矩阵 {{b+a,b},{b,a}}, B={{1,1},{1,0}},通过快速幂即可求得。这很容易推导的出来,假设A={{f(n+1),f(n)},{f(n),f(n-1)}},则A*B={{f(n+1)+f(n),f(n+1)},{f(n+1),f(n)}}=F(n+1),所以,当A初始值为{{b+a,b},{b,a}}时,我们可以用F(n)=A*B^(n-1)快速计算斐波那契的第n项。代码如下:
#include<stdio.h>void fun(__int64 b[][2],__int64 a[][2]){//矩阵连乘快速幂 __int64 c[2][2]={0},i,j,k; for(i=0;i<2;i++){ for(j=0;j<2;j++){ for(k=0;k<2;k++){ c[i][j]=c[i][j]+b[i][k]*a[k][j]; } } } for(i=0;i<2;i++){ for(j=0;j<2;j++){ b[i][j]=c[i][j]; } }}int main(){ __int64 a[2][2],b[2][2]={{1,1},{1,0}},c[2][2]={{1,0},{0,1}},i,j,x,y,n,t; while(scanf("%I64d %I64d %I64d",&x,&y,&n)!=EOF){ a[0][0]=x+y,a[0][1]=y,a[1][0]=y,a[1][1]=x; b[0][0]=1,b[0][1]=1,b[1][0]=1,b[1][1]=0; c[0][0]=1,c[0][1]=0,c[1][0]=0,c[1][1]=1; t=n-1; while(t>0){ if(t%2==1){ fun(c,b); } fun(b,b); t=t/2; } fun(a,c); printf("%I64d\n",a[1][0]); }}
- HDU4549M-斐波那契数列(矩阵快速幂,二分幂)
- hdu4549M斐波那契数列 矩阵快速幂 + 费马小定理
- M斐波那契数列(hdu4549矩阵二分幂+二分快速幂)
- hdu 4549 M斐波那契数列(费马小定理 + 二分快速幂 + 矩阵快速幂)
- hdu3117(斐波那契数列+矩阵快速幂)
- 矩阵快速幂 斐波那契数列
- EOJ 1499 【斐波那契数列】【矩阵快速幂】
- hdu4549 M斐波那契数列(矩阵快速幂)
- hihoCoder1143 DP 斐波那契数列矩阵快速幂
- nod51-1242斐波那契数列-矩阵快速幂
- 斐波那契数列矩阵快速幂
- 斐波那契数列 打表+矩阵快速幂
- 【矩阵快速幂】 斐波那契数列求解。
- 斐波那契数列(矩阵快速幂)
- *矩阵快速幂(斐波那契数列模板)
- 矩阵快速幂(斐波那契数列)
- HDU4549 M斐波那契数列【矩阵快速幂】
- 斐波那契数列 (矩阵快速幂)
- 全亮全灭点亮mini2440的设备驱动
- 浅谈:国内软件公司为何无法做大做强
- jQuery中创建实例与原型继承揭秘
- POJ 1222 EXTENDED LIGHTS OUT
- 黑马程序员--第二十五天:正则表达式
- HDU4549M-斐波那契数列(矩阵快速幂,二分幂)
- 重拾ubuntu-记录点滴持续更新
- [C/C++标准库]_[初级]_[使用auto_ptr智能指针]
- linux测试磁盘读写IO速度的方法
- 果敢见闻录(一):虎踞龙盘今胜昔
- OpenCV计算连通区域数目与最大连通区域并标示出
- java中hibernate的Serializable解析
- 闹钟学习
- HDU 4549 M斐波那契数列