luoguP5789 [TJOI2017]可乐(数据加强版) 矩阵乘法

比较简单的一道题.     

矩阵乘法,唯一需要注意的地方就是这道题需要维护前缀和.   

那么我们就多增加一个变量 $g$,表示前缀和,然后在设置矩阵的时候将 $g$ 要乘的一列中的元素都设置成前缀和即可.         

做这种题的时候可以先打一个暴力来测试一下边界什么的,然后再去用矩阵乘法来优化.   

code: 

#include <cstdio>  
#include <algorithm>
#include <cstring> 
#define N 103
#define mod 2017 
#define ll long long 
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;   
int n,m,a[N][N];     
struct M {       
    int ma[N][N];  
    M(int x=0) {  
        memset(ma,0,sizeof(ma));  
        for(int i=1;i<N;++i) ma[i][i]=x;   
    }    
    int *operator[](int x) { return ma[x]; }    
    M operator*(const M b) const  {  
        M c;   
        for(int i=1;i<N;++i) 
            for(int j=1;j<N;++j) 
                for(int k=1;k<N;++k) {  
                    (c.ma[i][j]+=ma[i][k]*b.ma[k][j]%mod)%=mod;   
                }   
        return c;  
    }   
    friend M operator^(M x,int y) {  
        M tmp(1);   
        while(y) {  
            if(y&1) tmp=tmp*x;  
            x=x*x;
            y>>=1; 
        } 
        return tmp;  
    }
}c0,X;       
int main() {  
    // setIO("input");
    scanf("%d%d",&n,&m);     
    int x,y,z;  
    for(int i=1;i<=n;++i) c0[i][i]=1;    
    for(int i=1;i<=m;++i) {     
        scanf("%d%d",&x,&y);  
        c0[x][y]=c0[y][x]=1;   
    }    
    for(int i=1;i<=n;++i) {  
        for(int j=1;j<=n;++j) c0[i][n+1]+=c0[i][j];     
    }   
    c0[n+1][n+1]=1;     
    X[1][1]=X[1][n+1]=1;     
    int T; 
    scanf("%d",&T); 
    X=X*(c0^T);                       
    printf("%d\n",X[1][n+1]);     
    return 0;
}

  

posted @ 2020-07-05 08:07  EM-LGH  阅读(179)  评论(0编辑  收藏  举报