1898: [Zjoi2005]Swamp 沼泽鳄鱼

矩阵乘法。

邻接矩阵用矩阵乘法可以得到最后的方案数

食人鱼是周期性的移动可以用12个矩阵表示。12个矩阵乘在一起得到第13个矩阵。

然后k/12的部分用第13个矩阵快速幂转移,再乘下剩余的矩阵。

#include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long 
using namespace std;
const int maxn = 50 + 10;
const int mod = 10000;

int n,m,p1,p2,k,nf;
int t[maxn],q[maxn][maxn];

struct Matrix {
    int a[maxn][maxn];
    
    int* operator [] (int x) {
        return a[x];
    }
    
    Matrix operator * (Matrix b) {
        Matrix res;
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        for(int k=1;k<=n;k++)
            res[i][k]=(res[i][k]+a[i][j]*b[j][k])%mod;
        return res;
    }
    
    Matrix operator ^ (int e) {
        Matrix res,tmp=*this;
        res.init();
        while(e) {
            if(e&1) res=res*tmp;
            tmp=tmp*tmp;
            e>>=1;
        }
        return res;
    }
    
    void init() {
        memset(a,0,sizeof(a));
        for(int i=1;i<=n;i++) 
            a[i][i]=1;
    }
    
    Matrix() {
        memset(a,0,sizeof(a));    
    }
}a[15],b,f;

void build() {
    scanf("%d%d%d%d%d",&n,&m,&p1,&p2,&k);
    p1++; p2++;
    for(int i=1,u,v;i<=m;i++) {
        scanf("%d%d",&u,&v);
        u++; v++;
        b[u][v]=b[v][u]=1;
    }                                                                                   
                                                            
    scanf("%d",&nf);
    for(int i=1;i<=nf;i++) {
        scanf("%d",&t[i]);
        for(int j=0;j<t[i];j++) {
            scanf("%d",&q[i][j]);
            q[i][j]++;    
        }
    }
    
    for(int i=1;i<=12;i++) {
        a[i]=b;        
        for(int j=1,v;j<=nf;j++) {
            v=q[j][i%t[j]];
            for(int k=1;k<=n;k++) a[i][k][v]=0;
        }
    }
    
    b.init();
    for(int i=1;i<=12;i++) b=b*a[i];
    f.init();
     f=f*(b^(k/12));
        
    for(int i=1;i<=(k%12);i++) f=f*a[i];    
    printf("%d\n",f[p1][p2]);
}

int main() {
    build();
    return 0;    
}
posted @ 2016-07-16 16:40  invoid  阅读(391)  评论(0编辑  收藏  举报