【矩阵乘法+快速乘】BZOJ2875-[NOI2012]随机数生成器
【题目大意】
已知Xn+1=(aXn+c) mod m,求Xn mod g。
【思路】
get到了longlong乘法的正确方法,快速乘。什么是快速乘呢?
简单来讲,快速幂就是模拟了二进制的竖式乘法。如:
10101 × 1011 = 10101*1+10101*2^1*1+10101*2^2*0+10101*2^3*1
代码如下:
long long multi(long long a,long long b,long long m) { long long ans=0; while(b) { if(b&1) (ans+=a) %= m; (a=a*2) %= m; b/=2; } return ans; }
接下来本题的方法就是据矩阵乘法的快速幂
(a 0
c 1)自乘n次即可
注意函数里也不要忘记了开longlong..一开始我函数里面的n写成了int,WA了一发。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 typedef long long ll; 7 ll matrix[2][2],ans_matrix[2][2]; 8 ll m,n,a,c,g,x0; 9 10 ll ksc(ll a,ll b) 11 { 12 ll ans=0; 13 while (b) 14 { 15 if (b&1) ans=(ans+a)%m; 16 a=(a<<1)%m; 17 b>>=1; 18 } 19 return ans; 20 } 21 22 void ksm(ll n) 23 { 24 ans_matrix[0][0]=ans_matrix[1][1]=1; 25 ans_matrix[0][1]=ans_matrix[1][0]=0; 26 while (n) 27 { 28 if (n&1) 29 { 30 ans_matrix[0][0]=ksc(ans_matrix[0][0],matrix[0][0]); 31 ans_matrix[1][0]=(ksc(ans_matrix[1][0],matrix[0][0])+matrix[1][0])%m; 32 } 33 n>>=1; 34 ll tmp1=ksc(matrix[0][0],matrix[0][0]); 35 ll tmp2=(ksc(matrix[1][0],matrix[0][0])+matrix[1][0])%m; 36 matrix[0][0]=tmp1,matrix[1][0]=tmp2; 37 } 38 } 39 40 void init() 41 { 42 scanf("%lld%lld%lld%lld%lld%lld",&m,&a,&c,&x0,&n,&g); 43 matrix[0][0]=a%m,matrix[0][1]=0,matrix[1][0]=c%m,matrix[1][1]=1; 44 } 45 46 void get_ans() 47 { 48 ll ans=(ksc(ans_matrix[0][0],x0)+ans_matrix[1][0])%m; 49 ans%=g; 50 printf("%lld",ans); 51 } 52 53 int main() 54 { 55 //freopen("randoma.in","r",stdin); 56 //freopen("randoma.out","w",stdout); 57 init(); 58 ksm(n); 59 get_ans(); 60 return 0; 61 }