zoukankan      html  css  js  c++  java
  • [HDU4532]湫秋系列故事——安排座位

    题面在这里

    description

    (n)种颜色的小球,每种颜色的小球有(a_i)个;
    要把它们摆成一排,求相邻小球颜色不相同的摆放方案数。
    任意两个合理的安排方法,只要有一个位置的同学不同,都被认为是不同的。

    data range

    [nle 50,a_ile 50,sum a_ile 500 ]

    solution

    鸣谢YCB

    以下先考虑可重排列的情况

    考虑容斥:

    [Ans=sum_{i=0}^{n-1}(-1)^{i}f(i) ]

    其中(f(x))表示至少有(x)对相邻同色球的方案数。

    直接求多项式(f(x))不好求,我们先考虑一种颜色。

    由于可重排列的方案数(P=frac{(sum a_i)!}{sum(a_i!)})
    对于一种颜色的小球,构造多项式

    [g_i(x)=sum_{j=0}^{a_i-1}(-1)^{j}frac{1}{(a_i-j)!}E(a_i,a_i-j)x^{j} ]

    其中(E(i,j))表示把(i)个相同的小球分成(j)段的方案数,
    相当于在(i-1)个空隙中选(j-1)块隔板,因此(E(i,j)=inom{i-1}{j-1})

    于是$$f(x)=(sum_{i=1}^{n} a_i)prod_{i=1}^{n}g_i(x)$$
    直接暴力多项式乘法即可,复杂度为(O(n(∑a_i)a_{max}))

    code

    #include<bits/stdc++.h>
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<iomanip>
    #include<cstring>
    #include<complex>
    #include<vector>
    #include<cstdio>
    #include<string>
    #include<bitset>
    #include<ctime>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<set>
    #define FILE "a"
    #define mp make_pair
    #define pb push_back
    #define RG register
    #define il inline
    using namespace std;
    typedef unsigned long long ull;
    typedef vector<int>VI;
    typedef long long ll;
    typedef double dd;
    const dd eps=1e-10;
    const int mod=1e9+7;
    const int N=505;
    const dd pi=acos(-1);
    il ll read(){
    	RG ll data=0,w=1;RG char ch=getchar();
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar();
    	return data*w;
    }
    
    il void file(){
    	freopen(FILE".in","r",stdin);
    	freopen(FILE".out","w",stdout);
    }
    
    il void upd(int &a,int b){a+=b;if(a>=mod)a-=mod;}
    il void dec(int &a,int b){if(!b)return;upd(a,mod-b);}
    il int poww(int a,int b){
    	RG int ret=1;
    	for(;b;b>>=1,a=1ll*a*a%mod)
    		if(b&1)ret=1ll*ret*a%mod;
    	return ret;
    }
    int fac[N],inv[N],C[N][N];
    il void init(){
    	fac[0]=1;for(RG int i=1;i<=500;i++)fac[i]=1ll*fac[i-1]*i%mod;
    	inv[500]=poww(fac[500],mod-2);
    	for(RG int i=499;i;i--)inv[i]=1ll*inv[i+1]*(i+1)%mod;
    	C[0][0]=1;
    	for(RG int i=1;i<=500;i++)
    		for(RG int j=0;j<=i;j++){
    			C[i][j]=C[i-1][j];
    			if(j)upd(C[i][j],C[i-1][j-1]);
    		}
    }
    
    int T,n,x,f[N],g[N],h[N],sum,ans,tot;
    int main()
    {
    	init();T=read();
    	for(RG int t=1;t<=T;t++){
    		n=read();ans=sum=0;memset(f,0,sizeof(f));f[0]=tot=1;
    		for(RG int i=1;i<=n;i++){
    			x=read();sum+=x;tot=1ll*tot*fac[x]%mod;
    			for(RG int j=0;j<x;j++){
    				g[j]=1ll*inv[x-j]*C[x-1][x-j-1]%mod;
    				if((j&1)&&g[j])g[j]=mod-g[j];
    			}
    			memset(h,0,sizeof(h));
    			for(RG int j=0;j<sum-x-i+2;j++)
    				for(RG int k=0;k<x;k++)
    					upd(h[j+k],1ll*f[j]*g[k]%mod);
    			swap(f,h);
    		}
    		for(RG int i=0;i<sum-n+2;i++)
    			upd(ans,1ll*f[i]*fac[sum-i]%mod);
    		printf("Case %d: %lld
    ",t,1ll*ans*tot%mod);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    scala与java的区别
    寒假第四天
    冲刺(第六天)
    冲刺(第五天)
    冲刺(第四天)
    冲刺(第三天)
    冲刺(第二天)
    第十周总结
    冲刺(第一天)
    文本中单词统计
  • 原文地址:https://www.cnblogs.com/cjfdf/p/9151547.html
Copyright © 2011-2022 走看看