codeforces 814E An unavoidable detour for home
正解:$dp$。
感觉这道题就是中国象棋的加强版。。我们要发现一些性质。
首先就是这个图肯定是一个按照$bfs$序分层的图,且每个点只往自己上面那一层连了一条边,每个点不可能向自己的上面超过两层的点连边。
又因为$l_{i}\leq l_{i+1}$,所以实际上$bfs$序相同的点是连续的。
然后我们就可以$dp$了,设$f[i][a][b][c][d]$表示处理了前i个点,上一层还有a个点度数为1,b个点度数为2,这一层还有c个点度数为1,d个点度数为2。
然后我们直接转移就行了,转移就是对于当前点,枚举它的连边情况,它肯定会往上一层连一条边,同时也可能往自己这一层连边,剩下的边就留给下一层就行了。
最终答案就是$f[n][0][0][0][0]$。
1 #include <bits/stdc++.h> 2 #define il inline 3 #define RG register 4 #define ll long long 5 #define rhl (1000000007) 6 7 using namespace std; 8 9 int f[2][51][51][51][51],du[51],n; 10 //f[i][a][b][c][d]表示处理了前i个点,上一层还有a个点度数为1,b个点度数为2,这一层还有c个点度数为1,d个点度数为2 11 12 il int gi(){ 13 RG int x=0,q=1; RG char ch=getchar(); 14 while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 15 if (ch=='-') q=-1,ch=getchar(); 16 while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); 17 return q*x; 18 } 19 20 il void add(RG int &x,RG int v){ 21 x+=v; if (x>=rhl) x-=rhl; return; 22 } 23 24 int main(){ 25 #ifndef ONLINE_JUDGE 26 freopen("home.in","r",stdin); 27 freopen("home.out","w",stdout); 28 #endif 29 n=gi(); 30 for (RG int i=1;i<=n;++i) du[i]=gi(); 31 f[0][du[1]==2][du[1]==3][du[2]==2][du[2]==3]=1; 32 for (RG int i=2,pre=1,cur=0;i<n;++i,pre=cur,cur^=1){ 33 memset(f[pre],0,sizeof(f[pre])); 34 for (RG int a=0;a<=i;++a) 35 for (RG int b=0;a+b<=i;++b) 36 for (RG int c=0;a+b+c<=i;++c) 37 for (RG int d=0,res;a+b+c+d<=i;++d){ 38 res=f[cur][a][b][c][d]; if (!res) continue; 39 if (!a && !b){ 40 if (c || d) add(f[cur][c][d][0][0],res); continue; 41 } 42 if (du[i+1]==2){ 43 if (a){ 44 add(f[pre][a-1][b][c+1][d],1LL*res*a%rhl); 45 if (c) add(f[pre][a-1][b][c-1][d],1LL*res*a*c%rhl); 46 if (d) add(f[pre][a-1][b][c+1][d-1],1LL*res*a*d%rhl); 47 } 48 if (b){ 49 add(f[pre][a+1][b-1][c+1][d],1LL*res*b%rhl); 50 if (c) add(f[pre][a+1][b-1][c-1][d],1LL*res*b*c%rhl); 51 if (d) add(f[pre][a+1][b-1][c+1][d-1],1LL*res*b*d%rhl); 52 } 53 } else{ 54 if (a){ 55 add(f[pre][a-1][b][c][d+1],1LL*res*a%rhl); 56 if (c) add(f[pre][a-1][b][c][d],1LL*res*a*c%rhl); 57 if (d) add(f[pre][a-1][b][c+2][d-1],1LL*res*a*d%rhl); 58 if (c && d) add(f[pre][a-1][b][c][d-1],1LL*res*a*c*d%rhl); 59 if (c>=2) add(f[pre][a-1][b][c-2][d],1LL*res*(a*c*(c-1)>>1)%rhl); 60 if (d>=2) add(f[pre][a-1][b][c+2][d-2],1LL*res*(a*d*(d-1)>>1)%rhl); 61 } 62 if (b){ 63 add(f[pre][a+1][b-1][c][d+1],1LL*res*b%rhl); 64 if (c) add(f[pre][a+1][b-1][c][d],1LL*res*b*c%rhl); 65 if (d) add(f[pre][a+1][b-1][c+2][d-1],1LL*res*b*d%rhl); 66 if (c && d) add(f[pre][a+1][b-1][c][d-1],1LL*res*b*c*d%rhl); 67 if (c>=2) add(f[pre][a+1][b-1][c-2][d],1LL*res*(b*c*(c-1)>>1)%rhl); 68 if (d>=2) add(f[pre][a+1][b-1][c+2][d-2],1LL*res*(b*d*(d-1)>>1)%rhl); 69 } 70 } 71 } 72 } 73 cout<<f[n&1][0][0][0][0]; return 0; 74 }