51nod 1231 记分牌

版权声明:原来这里可以拿来卖萌ヽ(・∀・)ノ https://blog.csdn.net/u012345506/article/details/81318629

折磨了一天想办法处理怎么用出度序列判断合法性,绝望的时候,同学说:

“这不是竞赛图么?”

“。。。。。。“

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;
};

猜你喜欢

转载自blog.csdn.net/u012345506/article/details/81318629