zoukankan      html  css  js  c++  java
  • P2579 [ZJOI2005]沼泽鳄鱼

    传送门

    显然可以列出 $dp$ 方程按时间转移

    发现数据 $n$ 很小,$K$ 很大,考虑矩阵快速幂优化转移

    但是不同时间的转移似乎不一样

    发现题目中单个鱼的移动有周期性,显然整体的移动也有周期性,发现个体的周期只有 $2,3,4$

    所以整体移动的周期最多也只有 $12$,所以考虑把 $12$ 步的转移一起考虑,最后剩下几步再暴力转

    这样每 $12$ 步的转移都一样了

    所以对于 $12$ 步一起的情况,直接把每一步的转移矩阵 $F[i],i in [1,12]$ 乘在一起变成另一个转移矩阵 $G$ 做快速幂就好了

    注意题目中点从 $0$ 标号,个人习惯从 $1$ 开始标号

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const int N=57,mo=1e4;
    int n,m,S,T,K;
    inline int fk(int x) { return x>=mo ? x-mo : x; }
    struct Matrix {
        int a[N][N];
        Matrix () { memset(a,0,sizeof(a)); }
        inline Matrix operator * (const Matrix &tmp) const {
            Matrix res;
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    for(int k=1;k<=n;k++)
                        res.a[i][j]=fk(res.a[i][j]+a[i][k]*tmp.a[k][j]%mo);
            return res;
        }
    }Ans,F[N],G;
    Matrix ksm(Matrix X,int y)
    {
        Matrix res;
        for(int i=1;i<=n;i++) res.a[i][i]=1;
        while(y)
        {
            if(y&1) res=res*X;
            X=X*X; y>>=1;
        }
        return res;
    }
    int main()
    {
        n=read(),m=read(),S=read()+1,T=read()+1,K=read();
        int a,b,tot,p[7];
        for(int i=1;i<=m;i++)
        {
            a=read()+1,b=read()+1;
            F[0].a[a][b]=F[0].a[b][a]=1;
        }
        for(int i=1;i<=12;i++) F[i]=F[0];
        tot=read();
        for(int i=1;i<=tot;i++)
        {
            a=read();
            for(int j=0;j<a;j++) p[j]=read()+1;
            for(int j=1;j<=12;j++)
            {
                int t=p[j%a];
                for(int k=1;k<=n;k++) F[j].a[k][t]=0;
            }
        }
        G=F[1]; for(int i=2;i<=12;i++) G=G*F[i];
        int t=K/12,s=K%12; Ans.a[1][S]=1;
        Ans=Ans*ksm(G,t);
        for(int i=1;i<=s;i++) Ans=Ans*F[i];
        printf("%d
    ",Ans.a[1][T]);
        return 0;
    }
  • 相关阅读:
    SDRAM(3):刷新和仲裁
    SDRAM(2):初始化
    SDRAM(1):基本介绍
    计数器(3):避免多计少计
    协议——SPI
    matlab数字图像处理 入门基础
    gVim编辑器——基本设置、常用命令、代码片段
    Pomelo的Router
    Pomelo聊天室框架
    Pomelo术语解释
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/11279085.html
Copyright © 2011-2022 走看看