【BZOJ1898】[ZJOI2005]沼澤鱷魚(矩陣快速冪,動態規劃)
阿新 • • 發佈:2018-10-04
表示 ear 構建 esp ++ 方案 set 沒有 ring
【BZOJ1898】[ZJOI2005]沼澤鱷魚(矩陣快速冪,動態規劃)
題面
BZOJ
洛谷
題解
先吐槽,說好了的鱷魚呢,題面裏面全是食人魚
看到數據範圍一眼想到矩乘。
先不考慮食人魚的問題,直接設\(f[i][j]\)表示\(j\)時刻到達了\(i\)號節點的方案數,轉移顯然。
接下來考慮食人魚的影響,顯然是在模\(2,3,4\)的意義下,某個特定余數時刻某個點不能到達,而\(lcm(2,3,4)=12\),所以顯然以\(12\)為周期,構建\(12\)個矩陣,每次一起乘就好了。多出來的部分再手動乘一下就沒有問題了。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; #define MAX 55 #define MOD 10000 inline int read() { int x=0;bool t=false;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=true,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return t?-x:x; } int n,m,St,Ed,K,a[MAX]; struct Matrix { int s[MAX][MAX]; void clear(){memset(s,0,sizeof(s));} void init(){clear();for(int i=1;i<=n;++i)s[i][i]=1;} int*operator[](int x){return s[x];} }T[15],S,g; Matrix operator*(Matrix a,Matrix b) { Matrix ret;ret.clear(); for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) for(int k=1;k<=n;++k) ret[i][j]=(ret[i][j]+a[i][k]*b[k][j])%MOD; return ret; } Matrix fpow(Matrix a,int b) { Matrix s;s.init(); while(b){if(b&1)s=s*a;a=a*a;b>>=1;} return s; } int main() { n=read();m=read();St=read()+1;Ed=read()+1;K=read(); for(int i=1;i<=m;++i) { int u=read()+1,v=read()+1; g[u][v]=g[v][u]=1; } for(int i=1;i<=12;++i)T[i]=g; int nf=read(); while(nf--) { int t=read(); for(int i=0;i<t;++i)a[i]=read()+1; for(int i=1;i<=12;++i) for(int j=1;j<=n;++j) T[i][j][a[i%t]]=0; } S.init();for(int i=1;i<=12;++i)S=S*T[i]; S=fpow(S,K/12); for(int i=1;i<=K%12;++i)S=S*T[i]; printf("%d\n",S[St][Ed]); return 0; }
【BZOJ1898】[ZJOI2005]沼澤鱷魚(矩陣快速冪,動態規劃)