J. u's的影响力
题目:
输入(n,x,y,a,b) 。输出 (x^{f(n-2)}*y^{f(n-1)}*a^{[f(n)-1]*b}) .其他f(i)表示Fibonacci数值
题解:
- 通过观察前几项得到上面的公式。利用矩阵快速幂可以计算很大的Fibonacci数,然后用快速幂求结果。
- 快速幂中,如果x是模数的倍数,那么对于x=0,y=0的情况,qpow(0,0) = 1,但是应该输出0,这一点要特判一下。
- 根据费马小定理,若 (p) 是正数,则对任意整数 (a) ,有 (a^{p} equiv a (mod p)) 。两边同时除 (a) 得, (a^{p-1} equiv 1 (mod p)) . 所以可以通过对幂取模来实现降幂。
推荐博客:矩阵构造方法
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MA=1e5+5;
const ll mod=1e9+7;
const ll P=1e9+6;
struct mat{
ll m[3][3];
mat(){memset(m,0,sizeof(m));}
};
mat mul(mat x,mat y){ //矩阵乘法
mat res;
for(int i=0;i<3;++i)
for(int j=0;j<3;++j)
for(int k=0;k<3;++k)
res.m[i][j]=(res.m[i][j]+x.m[i][k]*y.m[k][j])%P;
return res;
}
mat power(mat A, ll n){ //矩阵快速幂
mat c=A,res;
for(int i=0;i<3;++i) res.m[i][i]=1;
while(n){
if(n&1) res=mul(res,c);
c=mul(c,c);
n>>=1;
}
return res;
}
ll qpow(ll x,ll y){ //快速幂
if(x%mod==0) return 0;
ll res=1;
while(y){
if(y&1) res=(res*x)%mod;
x=(x*x)%mod;
y>>=1;
}
return res;
}
ll n,x,y,a,b;
int main()
{
scanf("%lld%lld%lld%lld%lld",&n,&x,&y,&a,&b);
x%=mod, y%=mod, a%=mod , b%=P;
if(n == 1) printf("%lld
",x);
else if(n == 2) printf("%lld
",y);
else{
mat A,B,C; //辅助矩阵
ll f1,f2,f3; //辅助变量,存三个Fibonacci值
A.m[0][0] = 1, A.m[0][1] = 1, A.m[1][0] = 1;
B.m[0][0] = 0, B.m[1][0] = 1;
C=mul(power(A,n-2) , B); //计算F(n-2)
f1=C.m[0][0] ;
C=mul(power(A,n-1) , B); //计算F(n-1)
f2=C.m[0][0] ;
C=mul(power(A,n) , B); //计算F(n);
f3=b*(C.m[0][0] -1 +P ) %P;
printf("%lld
",qpow(x,f1)%mod *qpow(y,f2)%mod * qpow(a,f3)%mod);
}
return 0;
}