Xn数列
题目描述 Description
给你6个数,m, a, c, x0, n, g
Xn+1 = ( aXn + c ) mod m,求Xn
m, a, c, x0, n, g<=10^18
输入描述 Input Description
一行六个数 m, a, c, x0, n, g
输出描述 Output Description
输出一个数 Xn mod g
样例输入 Sample Input
11 8 7 1 5 3
样例输出 Sample Output
2
建构一个矩阵,利用矩阵预算求解这个不难(具体看代码),关键在于两数相乘是会超LL范围;
所以这里介绍一种快速幂求乘法:
a,b是两个要相乘的数,
循环是b/2,a*2(使积不变)如果b&1==1,则需要累加一个这一时段的a值;
ll mul(ll a,ll b){
ll ans=0;
for(;b;b>>=1,(a<<=1)%=P)
if(b&1) (ans+=a)%=P;
return ans;
}
#include<cstdio> #include<cstring> #define LL long long typedef long long ok[3][3]; LL m,a,c,g,n,x,tot; ok ans={0},w,f,w2; LL mul(LL x,LL y) { LL answ=0; for(;y;y>>=1,(x<<=1)%=m) if(y&1)(answ+=x)%=m; return answ; } void ma(ok &t) { memcpy(w,t,sizeof(w)); memcpy(w2,f,sizeof(w2)); for(int i=1;i<=2;i++) for(int j=1;j<=2;j++) { t[i][j]=0; for(int k=1;k<=2;k++) t[i][j]=(t[i][j]+mul(w[i][k],w2[k][j]))%m; } } int main() { scanf("%lld%lld%lld%lld%lld%lld",&m,&a,&c,&x,&n,&g); f[1][1]=a%m;f[1][2]=0; f[2][1]=f[2][2]=1; for(int i=1;i<=2;i++)ans[i][i]=1; while(n) { if(n&1)ma(ans); n>>=1; ma(f); } tot=(mul(ans[1][1],x%m)+mul(ans[2][1],c%m))%m; printf("%lld\n",tot%g); //for(;;); return 0; }