51nod 1231 記分牌
阿新 • • 發佈:2018-12-31
折磨了一天想辦法處理怎麼用出度序列判斷合法性,絕望的時候,同學說:
“這不是競賽圖麼?”
“。。。。。。“
Landau’s Theorem:
當出度序列按非遞減排序後前
個的和不小於
即合法。不會證。
直接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;
};