[vijos1725&bzoj2875]随机数生成器<矩阵乘法&快速幂&快速乘>

题目链接:https://vijos.org/p/1725

    http://www.lydsy.com/JudgeOnline/problem.php?id=2875

这题是前几年的noi的题,时间比较久远了所以就不是那么的难了

这是一个非常裸的矩阵乘法,一般矩阵乘法就是矩阵+快速幂

只是这道题在矩阵乘法的时候单纯的乘法会溢出,所以还要用到快速乘法

网上也有说用long double黑科技的,虽然我不是很懂那个东东

 

构造矩阵

单位矩阵a,c

              0,1

答案矩阵   Xi-1

                 1

我的这个矩阵构造可能和一般的不同,主要是我受斐波拉契的毒害太深了QAQ

这题我一开始只是用的int,只过了一半,longlong后过了17组,最后三组加上快速乘优化才成功通过

然后如果是在vijos提交要注意一点就是在vijos上输出longlong型要用I64d来输出

 

 1 #include
 2 #include
 3 #include
 4 #include
 5 #include
 6 #include
 7 #include
 8 #define ll long long
 9 using namespace std;
10 
11 ll n,m,a,c,g,x0;
12 ll ans[4][4],b[4][4];
13 
14 void read(ll & xx){
15     xx=0;ll ff=1;char ch=getchar();
16     while(ch<'0'||ch>'9'){if(ch=='-')ff=-1;ch=getchar();}
17     while(ch>='0'&&ch<='9'){xx=xx*10+ch-'0';ch=getchar();}
18     xx*=ff;
19 }
20 
21 ll sum(ll x,ll y){
22     ll cnt=0;
23     while(y){
24         if(y&1){
25             cnt=(cnt+x)%m;
26         }y>>=1;x=(x+x)%m;
27     }return cnt;
28 }
29 
30 void add(){
31         ll z[4][4];memset(z,0,sizeof(z));
32         for(int i=1;i<=2;i++){
33             for(int j=1;j<=2;j++){
34                 for(int k=1;k<=2;k++){
35                     z[i][j]=(z[i][j]%m+sum(b[k][j],b[i][k])%m)%m;
36                 }
37             }
38         }        
39         for(int i=1;i<=2;i++)
40         for(int j=1;j<=2;j++)
41             b[i][j]=z[i][j]%m;    
42 }
43 
44 void mul(ll y){
45     while(y){
46         if(y&1){
47             ll z[4][4];z[1][1]=z[2][1]=0;
48             for(int i=1;i<=2;i++){
49                 for(int j=1;j<=1;j++){
50                     for(int k=1;k<=2;k++){
51                         z[i][j]=(z[i][j]%m+sum(ans[k][j],b[i][k])%m)%m;
52                     }
53                 }
54             }
55             ans[1][1]=z[1][1]%m; 
56         }
57         y>>=1;
58         add();
59     }
60 }
61 
62 int main(){
63     read(m),read(a),read(c),read(x0),read(n),read(g);
64     ans[1][1]=x0%m;ans[2][1]=1;
65     b[1][1]=a%m;b[1][2]=c%m;b[2][2]=1;
66     mul(n);
67     //printf("%lld",ans[1][1]%g);
68     cout<1][1]%g;
69 }
View Code

【总结】

活用快速幂的模板,毕竟这东西真的很神奇

 

你可能感兴趣的:([vijos1725&bzoj2875]随机数生成器<矩阵乘法&快速幂&快速乘>)