[luogu2044][NOI2012] 随机数生成器 [矩阵快速幂]

题面:

传送门

思路:

看一眼这个公式:

$x\left[n+1\right]=\left(a\ast x\left[n\right]+c\right) mod m$

递推,数据范围$n\leq 10^18$,自然想到矩阵快速幂

构造如下矩阵:

状态矩阵:

$\begin{bmatrix}x\lbrack i\rbrack&1\end{bmatrix}$

转移矩阵:

$\begin{bmatrix}a&0\\c&1\end{bmatrix}$

从x[0]开始做转移矩阵的n次幂,再乘上状态矩阵即可

 

Code:

 1 // luogu-judger-enable-o2
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<algorithm>
 6 #define ll long long
 7 using namespace std;
 8 inline ll read(){
 9     ll re=0,flag=1;char ch=getchar();
10     while(ch>'9'||ch<'0'){
11         if(ch=='-') flag=-1;
12         ch=getchar();
13     }
14     while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
15     return re*flag;
16 }
17 ll n,m,A,C,st,g;
18 ll mul(ll l,ll r){
19     ll re=0;if(l<r) swap(l,r);
20     while(r){
21         if(r&1ll) re=(re+l)%m;
22         r>>=1ll;l=(l+l)%m;
23     }
24     return re;
25 }
26 struct ma{
27     ll a[10][10],n,m;
28     ma(){memset(a,0,sizeof(a));n=m=0;}
29     void clear(){memset(a,0,sizeof(a));n=m=0;}
30     const void operator =(const ma &b){
31         n=b.n;m=b.m;ll i,j;
32         for(i=1;i<=n;i++) for(j=1;j<=n;j++) a[i][j]=b.a[i][j];
33     }
34 }a,b;
35 ma mmul(ma x,ma y){
36     ma re;re.n=x.n;re.m=y.m;ll i,j,k;
37     for(i=1;i<=x.n;i++){
38         for(j=1;j<=y.m;j++){
39             for(k=1;k<=x.m;k++){
40                 re.a[i][j]+=mul(x.a[i][k],y.a[k][j]);
41                 re.a[i][j]%=m;
42             }
43         }
44     }
45     return re;
46 }
47 ma ppow(ma x,ma y,ll t){
48     while(t){
49         if(t&1ll) x=mmul(x,y);
50         y=mmul(y,y);t>>=1ll;
51     }
52     return x;
53 }
54 int main(){
55     m=read();A=read();C=read();st=read();n=read();g=read();
56     a.n=1;a.m=2;b.n=b.m=2;
57     a.a[1][1]=st;a.a[1][2]=1;
58     b.a[1][1]=A;b.a[2][1]=C;b.a[2][2]=1;
59     ma ans=ppow(a,b,n);
60     printf("%lld",ans.a[1][1]%g);
61 }

 

posted @ 2018-03-31 11:29  dedicatus545  阅读(290)  评论(0编辑  收藏  举报