• 洛谷P3758


    Portal

    Description

    给出一张(n(nleq30))个点(m(mleq100))条边的无向图。初始时有一个可乐机器人在点(1),这个机器人每秒会做出以下三种行为之一:原地不动,走向相邻点,自爆(自爆后就不能动了)。求经过(t(tleq10^6))秒后可乐机器人的行动方案数。

    Solution

    矩阵乘法优化DP。
    首先改一下原图:每个点向自己连一条自环;建立一个点(n+1)表示自爆,其余每个点向(n+1)连一条有向边。然后原问题就简化成了在一个有向图上,每秒走向一个相邻的点。
    (dp[i][x])表示机器人在第(i)秒时在点(x)有多少种方案。做出邻接矩阵(M),则转移方程为:

    [ dp[i+1][v]=sum_{u=1}^n sum_{v=1}^n dp[i][u]M_{uv} $$ 是不是和矩阵乘法有点像?将$dp[i]$看做一个向量,则有$dp[i]=dp[i-1] imes M$。我们要求的是$dp[t]=dp[1] imes M^t$,那么只要做矩阵快速幂就好啦。 > 时间复杂度$O(n^3logt)$。 ##Code ```cpp //[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 ",ans); return 0; } ```]

  • 相关阅读:
    iOS开发-消息初认识
    小程序开发相关网址
    201703-4 地铁修建
    CCF 201703-3 Markdown
    UVALive 4998 Simple Encryption
    CCF 201609-4 交通规划
    CCF 201609-3 炉石传说
    UVALive 4270 Discrete Square Roots
    CCF 201604-2 俄罗斯方块
    codeforces 710E Generate a String
  • 原文地址:https://www.cnblogs.com/VisJiao/p/LgP3758.html
Copyright © 2020-2023  润新知