【xsy1103】隨機數表(RanMat)矩陣快速冪

題目大意:你生成了一個隨機數表,生成機制是這樣子的:c++

$a[i]=A1a[i-1]+A2(2≤i≤m)$spa

$b[i]=B1b[i-1]+B2(2≤i≤m)$code

$M[1][y]=a[y]%P,(1≤y≤m)$blog

$M[x][1]=b[x]%P,(2≤x≤n)$ci

$M[x][y]=(\sum\limits_{i=1}^{x-1}\sum\limits_{j=1}^{y-1} M[i][j])%P,(2≤x≤n,2≤y≤m)$it

有$k$組詢問,每次問你$M[x][y]$的值。class

數據範圍:$n≤50$,$m≤10^9$,$k≤10$,$P≤32768$隨機數

 

咱們考慮$y=1$和$x=1$的狀況,這兩種狀況直接等於$a$或$b$,直接矩陣快速冪就能夠了。im

對於非這兩種的狀況,咱們考慮一個$1\times n+2$的矩陣數據

咱們用這個矩陣的前$n$個數表示第i行的前綴和,第$n+1$個數爲$M[1][j]$的值,第$n+2$個數恆爲$1$,大概長這樣:

$\begin{bmatrix}
s(1,i),s(2,i)\cdots s(n-1,i),s(n,i),a[i],1
\end{bmatrix}$

其中$s(x,y)=\sum\limits_{i=1}^{y} M[x][i]$

而後,咱們考慮構造一個矩陣,使得上面這個矩陣乘上它後,能夠變成

$\begin{bmatrix}
s(1,i+1),s(2,i+1)\cdots s(n-1,i+1),s(n,i+1),a[i+1],1
\end{bmatrix}$

不難推出這個矩陣是長這樣的:

$\begin{bmatrix}1 , 1 , 1 ,\cdots 1 , 0 , 0\\0,1,1,\cdots 1,0,0\\0,0,1,\cdots 1,0,0\\ \vdots \ \ \ \ \ddots \ \ \ \ \ \ \vdots
\\ 0,0,0,\cdots 1,0,0\\
A1,0,0,\cdots A1,0\\
A2,0,0,\cdots A2,0\\ \end{bmatrix} $

假設咱們須要求$M[x][y]$,咱們能夠經過矩陣快速冪,先求出

$\begin{bmatrix}
s(1,y-1),s(2,y-1)\cdots s(n-1,y-1),s(n,y-1),a[y-1],1
\end{bmatrix}$

而後$M[x][y]$顯然等於$\sum\limits_{i=1}^{x-1} s(i,y-1)$。

而後就作完了。

完結撒花

 1 #include<bits/stdc++.h>
 2 #define M 55
 3 using namespace std;
 4 int MOD;
 5 struct mat{
 6     int a[M][M],n,m; mat(){memset(a,0,sizeof(a));}
 7     mat(int nn,int mm){n=nn; m=mm; memset(a,0,sizeof(a));}
 8     int* operator [](int x) {return a[x];}
 9     friend mat operator *(mat a,mat b){
10         mat c=mat(a.n,b.m);
11         for(int i=1;i<=c.n;i++)
12         for(int j=1;j<=c.m;j++)
13         for(int k=1;k<=b.n;k++)
14         c[i][j]=(c[i][j]+a[i][k]*b[k][j])%MOD;
15         return c;
16     }
17     void dw(){memset(a,0,sizeof(a)); for(int i=1;i<=n;i++) a[i][i]=1;}
18     friend mat operator ^(mat a,int b){
19         mat ans=mat(a.n,a.m); ans.dw();
20         while(b){
21             if(b&1) ans=ans*a;
22             a=a*a; b>>=1;
23         }
24         return ans;
25     }
26 };
27 
28 int n,m;
29 int a[M]={0},A1,A2,B1,B2;
30 int main(){
31     cin>>n>>m>>MOD;
32     cin>>a[1]>>B1>>B2;cin>>A1>>A2;
33     for(int i=2;i<=n;i++) a[i]=(a[i-1]*A1+A2)%MOD;
34     
35     mat f=mat(n+2,n+2),g=mat(1,n+2);
36     for(int i=1;i<=n;i++) g[1][i]=a[i]; 
37     g[1][n+1]=a[1]; g[1][n+2]=1;
38     
39     for(int i=1;i<=n;i++) for(int j=1;j<=i;j++) f[j][i]=1;
40     f[n+1][1]=f[n+1][n+1]=B1;
41     f[n+2][1]=f[n+2][n+1]=B2;
42     f[n+2][n+2]=1;
43     
44     int q; scanf("%d",&q);
45     while(q--){
46         int x,y; scanf("%d%d",&x,&y);
47         if(y==1) {printf("%d\n",a[x]); continue;}
48         mat F=f^(y-2);
49         mat ans=g*F;
50         if(x==1) {
51             ans=ans*f;
52             printf("%d\n",ans[1][n+1]); 
53             continue;
54         }
55         int sum=0;
56         for(int i=1;i<x;i++) sum=(sum+ans[1][i])%MOD;
57         printf("%d\n",sum);
58     }
59 }
相關文章
相關標籤/搜索