1. 程式人生 > >51nod 1231 記分牌

51nod 1231 記分牌

折磨了一天想辦法處理怎麼用出度序列判斷合法性,絕望的時候,同學說:

“這不是競賽圖麼?”

“。。。。。。“

Landau’s Theorem
當出度序列按非遞減排序後前 k 個的和不小於 k

( k 1 ) 2 即合法。不會證

直接dp就完事了。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std; //Container-- // #define clr(a) memset(a,0,sizeof(a)) typedef long long ll; const ll md=1e9+7;ll cb[41][41],dp[2][41][1600];int tr[41]; inline int _x(int n){return n*(n-1)/2;}; void _init(){ int i,j,k,d,t;for(i=0;i<=40;++i)for(cb[i][0]=1,j=1;j<=i;++j) cb[i][j]=(cb[i-1][j-1
]+cb[i-1][j])%md; }; void cl(){ int i,j,k,d,t,n,dn,a,b,ps,pc;for(scanf("%d",&n),clr(tr),dn=i=0;i<n;++i){ scanf("%d",&t); if(t<0)++dn; else tr[t]++; } for(clr(dp),ps=pc=0,b=1,dp[a=0][0][0]=1,i=0;i<n;++i){ for(clr(dp[b]),j=pc;j<=pc+dn;++j)for(k=ps;k<=_x(n);++k)if(dp[a][j][k]){ for(d=0;d<=dn-j+pc;++d){ if(k+(tr[i]+d)*i<_x(j+tr[i]+d))continue; dp[b][j+tr[i]+d][k+(tr[i]+d)*i]+=(dp[a][j][k]*cb[dn-(j-pc)][d]%md); dp[b][j+tr[i]+d][k+(tr[i]+d)*i]%=md; } } ps+=tr[i]*i,pc+=tr[i]; swap(a,b); } printf("%lld\n",dp[a][n][_x(n)]); }; int main(){ #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif int t;scanf("%d",&t);for(_init();t--;cl()); return 0; };