题目链接
欧拉降幂:
欧拉降幂参考博客
存欧拉函数模板:
ll phi(ll n) { ll ans = 1; for (ll i = 2; i*i <= n; i++) { if (n%i == 0) { n /= i; ans *= i - 1; while (n%i == 0) { n /= i; ans *= i; } } } if (n > 1) ans *= n - 1; return ans; }
然后解法:
f(1)=x f(1)=x^1 * y^0 * a^(1+0-1)b
f(2)= y f(2)= x^0 * y^1 * a^(0+1-1)b
f(3)=x * y * a^b f(3)=x * y * a^(1+1-1)b
f(4) = x * y^2 * a^2b f(4) = x * y^2 * a^(1+2-1)b
f(5) = x^2 * y^3 * a^4b f(5) = x^2 * y^3 * a^(2+3-1)b
f(6) = x^3 * y^5 * a^7b f(6) = x^3 * y^5 * a^(3+5-1)b
易得:f( n ) = x^fab(n-2) * y^fab(n-1) * a^(fab(n)-1)*b
鉴于a^(fab(n)-1)*b 指数过大,需要使用 欧拉降幂
鉴于fab(n) n比较大,需要使用 矩阵快速幂 求斐波拉契数
其次,当a%mod==0 时,即gcd(a,mod)!=1,而a^(fab(n)-1)*b算出来会是1,但是a^(fab(n)-1)*b%mod=0 ,则需要特判
#include<bits/stdc++.h> #define ll long long ll mod=1e9+7; using namespace std; ll n,x,y,a,b; ll res[2][2]; void mul(ll a[][2],ll b[][2] )//矩阵乘法 { ll t[2][2]; memset(t,0,sizeof(t)); for(int i=0;i<2;i++) { for(int j=0;j<2;j++) { for(int k=0;k<2;k++) t[i][j]+=a[i][k]%mod*b[k][j]%mod; t[i][j]%=mod; } } for(int i=0;i<2;i++) { for(int j=0;j<2;j++) a[i][j]=t[i][j]; } } void Pow(ll a[][2],ll p)//矩阵快速幂 { memset(res,0,sizeof(res)); for(int i=0;i<2;i++) res[i][i]=1; //!!!矩阵初始化 while(p) { if(p&1) mul(res,a); mul(a,a); p/=2; } } ll fab(ll n) { if(n<=2) return 1; ll tmp[2][2]; tmp[0][0]=1; tmp[0][1]=1; tmp[1][0]=1; tmp[1][1]=0; Pow(tmp,n-2); ll ans=(res[0][0]+res[0][1])%mod; return ans; } ll ksm(ll a,ll b)//快速幂 { ll ans=1; ll hh=a%mod;//!!!mod while(b) { if(b&1) ans*=hh; ans%=mod; hh*=hh; hh%=mod; b/=2; } return ans; } int main() { cin>>n>>x>>y>>a>>b; mod--;//费马小定理gcd(a,mod)==1 指数对1e9+6 取模 ll X=fab(n-2); ll Y=fab(n-1); ll A=(X+Y-1+mod)%(mod); A%=mod; mod++; if(n<=2) { if(n==1)printf("%lld\n",x%mod); else printf("%lld\n",y%mod); return 0; } if(a%mod==0||x%mod==0||y%mod==0)//要注意a是1000000007的倍数的特殊情况 即gcd(a,mod)!=1, //不能用费马小定律指数对1e9+6 取模。 { printf("0\n"); return 0; } ll ans=ksm(x,X)%mod*ksm(y,Y)%mod*ksm(ksm(a,b),A)%mod; printf("%lld\n",ans); return 0; }