标签:
题意:S1=a,Sn=a*(Sn-1)^k%m,且有(a,m)=1,给出i,求Si。
思路:首先我们可以写出Sn的通项a^(1+k+k^2+...k^n-1);其次注意到m的范围是10000以内,所以我们可以利用欧拉公式降幂。
注意到(a,m)=1;又欧拉定理可知a^x%m=a^(x%phi(m))*a^phi(m)%m,而a^phi(m)=1;所以
a^x%m=a^(x%phi(m))%m;
而幂是一个等比数列,可以利用快速矩阵幂计算,算出幂之后,再利用快速幂求出答案。
#include<cstdio> #include<cstring> using namespace std; typedef long long ll; const int maxn=10010; int euler[maxn]; ll a,k,m,n; int phi() { for(int i=0;i<maxn;i++) euler[i]=i; for(int i=2;i<maxn;i++) { if(euler[i]==i) { for(int j=i;j<maxn;j+=i) { euler[j]=euler[j]/i*(i-1); } } } } struct Matrix { ll a[2][2]; Matrix(){memset(a,0,sizeof(a));} Matrix operator* (const Matrix &p) { Matrix res; for(int i=0;i<2;i++) { for(int j=0;j<2;j++) { for(int k=0;k<2;k++) { res.a[i][j]+=(a[i][k]*p.a[k][j]%euler[m]); } res.a[i][j]%=euler[m]; } } return res; } }ans,base; Matrix quick_pow(Matrix base,ll n) { Matrix res; for(int i=0;i<2;i++) { res.a[i][i]=1; } while(n) { if(n&1) res=res*base; base=base*base; n>>=1; } return res; } ll pow(ll a,ll n) { ll ans=1; while(n) { if(n&1) ans=ans*a%m; a=a*a%m; n>>=1; } return ans; } void Matrix_init() { ans.a[0][0]=1; ans.a[0][1]=1; ans.a[1][0]=0; ans.a[1][1]=0; base.a[0][0]=k; base.a[0][1]=0; base.a[1][0]=1; base.a[1][1]=1; } int main() { ll x; phi(); while(~scanf("%lld%lld%lld%lld",&a,&k,&m,&n)) { Matrix_init(); ans=ans*quick_pow(base,n-1); x=ans.a[0][0]; x=pow(a%m,x)%m; printf("%lld\n",x); } return 0; }
2016湖大校赛 L题 The Sequence likes Ladder
标签:
原文地址:http://www.cnblogs.com/PrimeXuan/p/5532528.html