Luogu P3758 - [TJOI2017] Cola

Portal

Description

Give an undirected graph of \(n(n\leq30)\) points \(m(m\leq100)\) edges. Initially, there is a cola robot at the point \(1\) , this robot will do one of the following three behaviors every second: stay still, move to the adjacent point, self-explode (it can't move after self-exploding). Find the number of action plans of the cola robot after \(t(t\leq10^6)\) seconds.

Solution

Matrix multiplication optimizes DP.
First change the original image: each point connects a self-loop to itself; establish a point \(n+1\) to indicate self-destruction, and each other point connects a directed edge to \(n+1\) . Then the original problem simplifies to go to an adjacent point every second on a directed graph.
\(dp[i][x]\) indicates how many options the robot has at the point \(x\) at the \(i\) second. Make an adjacency matrix \(M\) , then the transition equation is: \[ dp[i+1][v]=\sum_{u=1}^n \sum_{v=1}^n dp[i][ Is u]M_{uv} \] a bit like matrix multiplication? Consider \(dp[i]\) as a vector, there is \(dp[i]=dp[i-1]\times M\) . What we require is \(dp[t]=dp[1]\times M^t\) , then just do the matrix fast power.

Time complexity \(O(n^3logt)\) .

Code

//[TJOI2017]可乐
#include <cstdio>
#include <cstring>
inline char gc()
{
    static char now[1<<16],*s,*t;
    if(s==t) {t=(s=now)+fread(now,1,1<<16,stdin); if(s==t) return EOF;}
    return *s++;
}
inline int read()
{
    int x=0; char ch=gc();
    while(ch<'0'||'9'<ch) ch=gc();
    while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc();
    return x;
}
const int P=2017;
const int N=40;
int n,m;
struct mtx
{
    int row,col; int x[N][N];
    mtx(int _row=0,int _col=0) {row=_row,col=_col; memset(x,0,sizeof x);}
    friend mtx operator *(mtx A,mtx B)
    {
        mtx C=mtx(A.row,B.col);
        for(int i=1;i<=A.row;i++)
            for(int k=1;k<=A.col;k++)
                for(int j=1;j<=B.col;j++)
                    C.x[i][j]=(C.x[i][j]+A.x[i][k]*B.x[k][j])%P;
        return C;
    }
};
mtx pow(mtx A,int k)
{
    mtx r=mtx(A.row,A.col),t=A;
    for(int i=1;i<=A.row;i++) r.x[i][i]=1;
    for(int i=k;i;i>>=1,t=t*t) if(i&1) r=r*t;
    return r;
}
int main()
{
    n=read(),m=read(); mtx tr=mtx(n+1,n+1);
    for(int i=1;i<=n+1;i++) tr.x[i][i]=1,tr.x[i][n+1]=1;
    for(int i=1;i<=m;i++)
    {
        int u=read(),v=read();
        tr.x[u][v]=tr.x[v][u]=1;
    }
    int t=read(); mtx r=mtx(1,n+1);
    r.x[1][1]=1; r=r*pow(tr,t);
    int ans=0;
    for(int i=1;i<=n+1;i++) ans=(ans+r.x[1][i])%P;
    printf("%d\n",ans);
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324575296&siteId=291194637