zoukankan      html  css  js  c++  java
  • 【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]%P,(1≤y≤m)$

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

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

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

    数据范围:$n≤50$,$m≤10^9$,$k≤10$,$P≤32768$

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

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

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

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

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

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

    $egin{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}$

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

    $egin{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]$,我们可以通过矩阵快速幂,先求出

    $egin{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]$显然等于$sumlimits_{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
    ",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
    ",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
    ",sum);
    58     }
    59 }
  • 相关阅读:
    Shell编程-02-Shell变量
    Linux 下强大的查找命令find
    DevOps 学院
    史上最详细、最全面的Hadoop环境搭建
    Linux 中10个命令链接操作符,帮助新手快速入门运维!
    25个Linux性能监控工具
    一文详解 Linux系统常用监控工具
    ansible 安装指南
    Tomcat管理页面
    Tomcat基础知识
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/10836371.html
Copyright © 2011-2022 走看看