【矩阵乘法+快速乘】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 } 

 

posted @ 2016-07-10 11:27  iiyiyi  阅读(69)  评论(0编辑  收藏