zoukankan      html  css  js  c++  java
  • 洛谷P2579 [ZJOI2005]沼泽鳄鱼(矩阵快速幂,周期)

    例题:现在豆豆已经选好了两座石墩Start和End,他想从Start出发,经过K个单位时间后恰好站在石墩End上。假设石墩可以重复经过(包括Start和End),他想请你帮忙算算,这样的路线共有多少种(当然不能遭到食人鱼的攻击)。

    输入格式:第一行包含五个正整数N,M,Start,End和K,分别表示石墩数目、石桥数目、Start石墩和End石墩的编号和一条路线所需的单位时间。石墩用0到N–1的整数编号。

    第2到M + 1行,给出石桥的相关信息。每行两个整数x和y,0 ≤ x, y ≤ N–1,表示这座石桥连接着编号为x和y的两座石墩。

    第M + 2行是一个整数NFish,表示食人鱼的数目。

    第M + 3到M + 2 + NFish行,每行给出一条食人鱼的相关信息。每行的第一个整数是T,T = 2,3或4,表示食人鱼的运动周期。接下来有T个数,表示一个周期内食人鱼的行进路线。

    如果T=2,接下来有2个数P0和P1,食人鱼从P0到P1,从P1到P0,……;

    如果T=3,接下来有3个数P0,P1和P2,食人鱼从P0到P1,从P1到P2,从P2到P0,……;

     如果T=4,接下来有4个数P0,P1,P2和P3,食人鱼从P0到P1,从P1到P2,从P2到P3,从P3到P0,……。

    豆豆出发的时候所有食人鱼都在自己路线上的P0位置,请放心,这个位置不会是Start石墩。

    输出格式:输出路线的种数,因为这个数可能很大,你只要输出该数除以10000的余数就行了。

    #include<cstdio>
    #include<cstring>
    const int mod = 10000;
    
    int x,y,n,m,k,s,t,fish;
    int res[30][5],tt[30];
    
    struct Node{
        int a[60][60];
        Node operator *(const Node &x)const{
            Node ans;
            memset(ans.a,0,sizeof(a));
            for(int i = 0; i < n; ++i)
                for(int t = 0; t < n; ++t)
                    for(int k = 0; k < n; ++k)
                        ans.a[i][t] = (ans.a[i][t]+a[i][k]*x.a[k][t]) % mod;
            return ans;
        }
    }h[15],bb,base,ans;
    
    void quick_pow(int k){
        while(k){
            if(k&1)  ans = ans*base;
            base = base*base;  k >>= 1;
        }
    }
    
    int main(){
        scanf("%d%d%d%d%d",&n,&m,&s,&t,&k);
        for(int i = 1; i <= m; ++i){
            scanf("%d%d",&x,&y);
            bb.a[x][y] = bb.a[y][x] = 1;
        } 
        scanf("%d",&fish);
        for(int i = 0; i < fish; ++i){
            scanf("%d",&tt[i]);
            for(int t = 0; t < tt[i]; ++t)  scanf("%d",&res[i][t]);
        }
        for(int i = 0; i < 12; ++i){
            h[i] = bb;
            for(int t = 0; t < fish; ++t)
                for(int k = 0; k < n; ++k)  h[i].a[k][res[t][(i+1)%tt[t]]] = 0;   
        }
        base = h[0];
        for(int i = 1; i < 12; ++i)  base = base*h[i];
        for(int i = 0; i < n; ++i)  ans.a[i][i] = 1;
        quick_pow(k/12);    
        for(int i = 1; i <= k%12; ++i)    ans = ans*h[i-1];
        printf("%d",ans.a[s][t]);
        return 0;
    }
    你只有十分努力,才能看上去毫不费力。
  • 相关阅读:
    SD卡测试
    测试人员可能会遇到的问题
    HDU 1024 Max Sum Plus Plus
    HDU 1176 免费馅饼
    HDU 1257 最少拦截系统
    HDU 1087 Super Jumping! Jumping! Jumping!
    poj 1328 Radar Installation
    poj 1753 Flip Game
    HDU 1003 Max Sum
    HDU 5592 ZYB's Premutation(BestCoder Round #65 C)
  • 原文地址:https://www.cnblogs.com/214txdy/p/14024230.html
Copyright © 2011-2022 走看看