【xsy1103】随机数表(RanMat)矩阵快速幂

题目大意:你生成了一个随机数表,生成机制是这样子的:

a[i]=A1a[i1]+A2(2im)

b[i]=B1b[i1]+B2(2im)

M[1][y]=a[y]

M[x][1]=b[x]

M[x][y]=(x1i=1y1j=1M[i][j])

k组询问,每次问你M[x][y]的值。

数据范围:n50m109k10P32768

 

我们考虑y=1x=1的情况,这两种情况直接等于ab,直接矩阵快速幂就可以了。

对于非这两种的情况,我们考虑一个1×n+2的矩阵

我们用这个矩阵的前n个数表示第i行的前缀和,第n+1个数为M[1][j]的值,第n+2个数恒为1,大概长这样:

[s(1,i),s(2,i)s(n1,i),s(n,i),a[i],1]

其中s(x,y)=yi=1M[x][i]

然后,我们考虑构造一个矩阵,使得上面这个矩阵乘上它后,可以变成

[s(1,i+1),s(2,i+1)s(n1,i+1),s(n,i+1),a[i+1],1]

不难推出这个矩阵是长这样的:

[1,1,1,1,0,00,1,1,1,0,00,0,1,1,0,0          0,0,0,1,0,0A1,0,0,A1,0A2,0,0,A2,0]

假设我们需要求M[x][y],我们可以通过矩阵快速幂,先求出

[s(1,y1),s(2,y1)s(n1,y1),s(n,y1),a[y1],1]

然后M[x][y]显然等于x1i=1s(i,y1)

然后就做完了。

完结撒花

复制代码
 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 }
复制代码
posted @   AlphaInf  阅读(363)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示