M斐波那契数列 HDU - 4549
思路:题意很简单,但是不好写,如果不知道幂的取模的话,基本就是tle。要知道如下定理:当m为素数,且a、m互质时, a^n % m = a^(n%(m-1)) % m。取模的问题解决了,就是矩阵快速幂了。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const ll mod=1000000007;
struct matrix{
ll x[2][2];
};
ll a1,b1,n;
//有如下定理:当m为素数,且a、m互质时, a^n % m = a^(n%(m-1)) % m。
ll gcd(ll a,ll b)
{
return b==0?a:gcd(b,a%b);
}
matrix multi(matrix a,matrix b){
matrix temp;
memset(temp.x,0,sizeof(temp.x));
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
{
temp.x[i][j]+=(a.x[i][k]*b.x[k][j])%(mod-1);
//if(gcd(temp.x[i][j],a1)==1) temp.x[i][j]%=(mod-1);
temp.x[i][j]%=(mod-1);
}
return temp;
}
matrix quick_multi(matrix a,ll m)//矩阵快速幂
{
matrix temp=a;
m--;
while(m){
if(m&1)
temp=multi(temp,a);//
a=multi(a,a);
m>>=1;
}
return temp;
}
ll quic_power(ll x,ll n)
{
ll result=1;
while(n)
{
if(n&1)
{
result*=x;
result%=mod;
}
x*=x;
x%=mod;
n>>=1;
}
return result;
}
int main()
{
while(scanf("%lld%lld%lld",&a1,&b1,&n)!=EOF)
{
matrix A,B;
memset(A.x,0,sizeof(A.x));
memset(B.x,0,sizeof(B.x));
B.x[0][0]=A.x[0][0]=A.x[0][1]=A.x[1][0]=1;
if(n<=1) n==0?printf("%lld\n",a1%mod):printf("%lld\n",b1%mod);
else
{
A=quick_multi(A,n-1);
B=multi(A,B);
//printf("%lld %lld\n",B.x[0][0],B.x[1][0]);
a1=quic_power(a1,B.x[1][0])%mod;
b1=quic_power(b1,B.x[0][0])%mod;
printf("%lld\n",(a1*b1)%mod);
}
}
return 0;
}