2019牛客暑期多校训练营(第五场)B:generator 1 (10进制快速幂)
题意:给定x0,x1,a,b,满足xi=a*xi-1+b*xi-2; 求xn,n<10^(10^6);
思路:10进制快速幂裸题。降幂来写好像也是可以的,但是循环节不是phi(mod),所以数学不好就还是用10进制快速幂吧。
10进制快速幂:复杂度O(n*log10*K^3); 复杂度也不低,所以要尽量少做mod运算。
#include<bits/stdc++.h> #define ll long long using namespace std; ll Mod; inline ll mul(ll x,ll y,ll p){ return x*y%p; } struct mat { ll M[3][3]; mat() { M[1][1]=M[1][2]=M[2][1]=M[2][2]=0; } mat friend operator *(mat a,mat b) { mat res; for(int k=1;k<=2;k++) for(int i=1;i<=2;i++) for(int j=1;j<=2;j++) res.M[i][j]+=a.M[i][k]*b.M[k][j];//每次取mod复杂度会过高。 for(int i=1;i<=2;i++) for(int j=1;j<=2;j++) res.M[i][j]%=Mod; return res; } mat friend operator ^(mat a,int x) { mat res; res.M[1][1]=res.M[2][2]=1LL; while(x){ if(x&1) res=res*a; a=a*a; x/=2; } return res; } }; char c[1000010];int x[1000010]; int main() { int T; ll X0,X1,A,B,N; T=1; while(T--){ scanf("%lld%lld%lld%lld",&X0,&X1,&A,&B); scanf("%s%lld",c+1,&Mod); int len=strlen(c+1); for(int i=1;i<=len;i++) x[i]=c[i]-'0'; x[len]--; for(int i=len;i>=1;i--){ if(x[i]<0) x[i-1]--,x[i]+=10; } mat base,a,ans; ans.M[1][1]=ans.M[2][2]=1; base.M[1][1]=A%Mod; base.M[1][2]=B%Mod; base.M[2][1]=1LL; a.M[1][1]=X1%Mod,a.M[2][1]=X0%Mod; for(int i=len;i>=1;i--){ if(x[i]) ans=ans*(base^x[i]); base=base^10; } ans=ans*a; printf("%lld\n",ans.M[1][1]%Mod); } return 0; }
It is your time to fight!