[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<cstdio>
2 #include<cstring>
3 #include<algorithm>
4 #include<cstdlib>
5 #include<cmath>
6 #include<iostream>
7 #include<queue>
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<<ans[1][1]%g;
69 }
【总结】
活用快速幂的模板,毕竟这东西真的很神奇