【xsy1103】随机数表(RanMat)矩阵快速幂
题目大意:你生成了一个随机数表,生成机制是这样子的:
a[i]=A1a[i−1]+A2(2≤i≤m)
b[i]=B1b[i−1]+B2(2≤i≤m)
M[1][y]=a[y]
M[x][1]=b[x]
M[x][y]=(x−1∑i=1y−1∑j=1M[i][j])
有k组询问,每次问你M[x][y]的值。
数据范围:n≤50,m≤109,k≤10,P≤32768
我们考虑y=1和x=1的情况,这两种情况直接等于a或b,直接矩阵快速幂就可以了。
对于非这两种的情况,我们考虑一个1×n+2的矩阵
我们用这个矩阵的前n个数表示第i行的前缀和,第n+1个数为M[1][j]的值,第n+2个数恒为1,大概长这样:
[s(1,i),s(2,i)⋯s(n−1,i),s(n,i),a[i],1]
其中s(x,y)=y∑i=1M[x][i]
然后,我们考虑构造一个矩阵,使得上面这个矩阵乘上它后,可以变成
[s(1,i+1),s(2,i+1)⋯s(n−1,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,y−1),s(2,y−1)⋯s(n−1,y−1),s(n,y−1),a[y−1],1]
然后M[x][y]显然等于x−1∑i=1s(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 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!