您的位置:首页 > 其它

2013金山西山居创意游戏程序挑战赛——初赛(2) B M斐波那契数 (hdu 4549 )

2013-05-19 19:31 465 查看
M斐波那契数列F
是一种整数数列,它的定义如下:

F[0] = a
F[1] = b
F
= F[n-1] * F[n-2] ( n > 1 )

现在给出a, b, n,你能求出F
的值吗?

思路:首先我们很容易得到F
的通项公式,对于F
=a^(f[n-1])*b^(f
),其中f
为斐波那契数列的第n项。由于我们要求的n很大(最大可达到10^9),所以我们不能直接求,这时我们可以用矩阵加速用O(logn)的复杂度来求f
,然后再用乘方快速幂求最终的结果。但是我们这里要求的结果是模上1000000007后(设为mod)的值,所以在矩阵加速的时候不能直接模上mod。这里用到了一个数论的知识,就是若a,b互质,则a^(b-1)%b==1,因为mod是一个素数,所以对于任何a,b(a,b<=10^9),都与mod互质,所以我们最终即是求 a^(f[n-1]%(mod-1))*b^(f
%(mod-1))%mod,这下就可以用矩阵快速幂来求解了。

代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string.h>
#define maxn 3
#define mod 1000000006
using namespace std;
typedef long long LL;
LL c[100][maxn][maxn];
LL ans[maxn][maxn];
int m=2;
void init(LL a[maxn][maxn],LL b[maxn][maxn], LL c[maxn][maxn])
{
int i,j,k;
LL tmp[maxn][maxn];
memset(tmp,0,sizeof(tmp));
for(i=1;i<=m;i++)
{
for(j=1;j<=m;j++)
{
for(k=1;k<=m;k++)
{
tmp[i][j]+=b[i][k]*c[k][j];
tmp[i][j]%=mod;
}
}
}
for(i=1;i<=m;i++)
{
for(j=1;j<=m;j++)
a[i][j]=tmp[i][j];
}
}
void build(int num)
{
if(num==1)
return;
build(num-1);
init(c[num],c[num-1],c[num-1]);
}
LL abmodn(LL a,LL b,LL n)
{
LL d=1,i,bi[40],num=0;
while(b>0)
{
bi[num++]=b%2;
b/=2;
}
for(i=num-1;i>=0;i--)
{
d=(d*d)%n;
if(bi[i])
d=(a*d)%n;
}
return d;
}
void solve(int n,int a,int b)
{
memset(ans,0,sizeof(ans));
int t[55],num=0;
while(n)
{
t[++num]=n%2;
n/=2;
}
build(num);
int i,j;
for(i=1;i<=m;i++)
{
for(j=1;j<=m;j++)
ans[i][j]=c[num][i][j];
}
for(i=1;i<num;i++)
{
if(t[i])
{
init(ans,ans,c[i]);
}
}
LL x=(ans[1][1]+ans[2][1])%mod,y=(ans[1][2]+ans[2][2])%mod;
LL ANS=(abmodn(a,x,mod+1)*abmodn(b,y,mod+1))%(mod+1);
printf("%I64d\n",ANS);
}
int main()
{
// freopen("dd.txt","r",stdin);
c[1][1][1]=0;
c[1][2][1]=c[1][1][2]=c[1][2][2]=1;
int a,b,n;
while(scanf("%d%d%d",&a,&b,&n)!=EOF)
{
if(n==0)
printf("%d\n",a);
else if(n==1)
printf("%d\n",b);
else if(n==2)
printf("%I64d\n",(LL)a*b%(mod+1));
else
{
solve(n-2,a,b);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐