【BZOJ 2875】 [Noi2012]随机数生成器
Description
给你6个数,m, a, c, x0, n, g
Xn+1 = ( aXn + c ) mod m,求Xn
m, a, c, x0, n, g<=10^18
Input
包含6个用空格分割的m,a,c,X0,n和g,其中a,c,X0是非负整数,m,n,g是正整数。
Output
输出一个数,即Xn mod g
Sample Input
11 8 7 1 5 3
Sample Output
2
构造矩阵
转移矩阵
|a0 0|
|1 1|
初始矩阵
|x0 C|
1 #include<cstdio> 2 #define ll long long 3 ll z[2][2],a[2][2]; 4 ll m,b,c,x0,n,p; 5 ll plus(ll x,ll y,ll p){ 6 ll s=0; 7 while (x>=1){ 8 if (x&1==1) s=(s+y)%p; 9 x=x>>1; 10 y=(y+y)%p; 11 } 12 return s; 13 } 14 15 void mult1(ll a[2][2],ll b[2][2]){ 16 ll c[2][2]; 17 for (int i=0;i<2;i++) for (int j=0;j<2;j++) c[i][j]=0; 18 for (int i=0;i<2;i++) 19 for (int j=0;j<2;j++) 20 for (int k=0;k<2;k++) 21 c[i][j]=(c[i][j]+plus(a[i][k],b[k][j],p))%p; 22 for (int i=0;i<2;i++) for (int j=0;j<2;j++) a[i][j]=c[i][j]; 23 } 24 25 void mult2(ll a[2][2],ll b[2][2]){ 26 ll c[2][2]; 27 for (int i=0;i<2;i++) for (int j=0;j<2;j++) c[i][j]=0; 28 for (int i=0;i<1;i++) 29 for (int j=0;j<2;j++) 30 for (int k=0;k<2;k++) 31 c[i][j]=(c[i][j]+plus(a[i][k],b[k][j],p))%p; 32 for (int i=0;i<1;i++) for (int j=0;j<2;j++) a[i][j]=c[i][j]; 33 } 34 35 void pow(ll z[2][2],ll n){ 36 ll ans[2][2]; 37 for (int i=0;i<2;i++) for (int j=0;j<2;j++) ans[i][j]=0; 38 ans[0][0]=1; ans[1][1]=1; 39 while (n>0){ 40 if (n%2==1) mult1(ans,z); 41 n=n>>1; 42 mult1(z,z); 43 } 44 for (int i=0;i<2;i++) for (int j=0;j<2;j++) z[i][j]=ans[i][j]; 45 } 46 47 int main(){ 48 scanf("%lld%lld%lld%lld%lld%lld",&p,&b,&c,&x0,&n,&m); 49 z[0][0]=b;z[1][0]=1;z[1][1]=1; 50 a[0][0]=x0;a[0][1]=c; 51 pow(z,n); 52 mult2(a,z); 53 printf("%lld",a[0][0]%m); 54 }