【JZOJ 5728】简单计数||

题目

Description
在这里插入图片描述

Input
在这里插入图片描述

Output
在这里插入图片描述

Sample Input
2
2 2

Sample Output
18

Data Constraint
在这里插入图片描述

思路

先考虑链是怎么做的
预处理f[i][j]表示i个分成j段,段与段之间有序,且乘上的了段的大小,这样的所有方案权值和。
现在相当于有第i个颜色有b[i]段,把这些合并,是的没有相邻两段颜色相同。
然后容斥
枚举c[i]第i个颜色实际上是有c[i]段
容斥系数为(-1)(b[i]-c[i])
划分数是C(b[i]-1,c[i]-1)
然后把ci卷积一下
考虑环上,使颜色1为开头一段,且不为结尾一段,然后可以旋转,也就是乘上n/1的段数,发现刚好不会算重。

参考:https://www.cnblogs.com/coldchair/p/12912470.html

代码

#include<bits/stdc++.h>
using namespace std; 
const int P=1000000007; 
const int N=55; 
const int MAXC=105; 
const int L=5005; 

int fact[L],invf[L],inv[L],f[L],g[L],g_[L],t[L]; 
int sum[MAXC][MAXC]; 
int c[N]; 
int n,sumc,maxc,ans; 

void add(int &x,int y){x=x+y>=P?x+y-P:x+y; }

int sig(int x){return x&1?P-1:1; }
int C(int n,int m){return 1ll*fact[n]*invf[m]%P*invf[n-m]%P; }

int power(int x,int y)
{
	int ret=1; 
	for (; y; y>>=1,x=1ll*x*x%P) if (y&1) ret=1ll*ret*x%P; 
	return ret; 
}

void pre()
{
	fact[0]=1; 
	for (int i=1; i<=sumc; ++i) fact[i]=1ll*fact[i-1]*i%P; 
	invf[sumc]=power(fact[sumc],P-2); 
	for (int i=sumc; i>=1; --i) invf[i-1]=1ll*invf[i]*i%P; 
	for (int i=1; i<=sumc; ++i) inv[i]=1ll*fact[i-1]*invf[i]%P; 
	sum[0][0]=1; 
	for (int i=1; i<=maxc; ++i)
		for (int j=1; j<=i; ++j)
			for (int k=1; k<=i; ++k)
				add(sum[i][j],1ll*sum[i-k][j-1]*k%P); 
}

int main()
{
	freopen("number.in","r",stdin),freopen("number.out","w",stdout); 
	n=read(),sumc=0; 
	for (int i=1; i<=n; ++i) sumc+=c[i]=read(),maxc=max(maxc,c[i]); 
	pre(),f[0]=1; 
	for (int i=1,curc=0; i<=n; ++i)
	{
		for (int j=1; j<=c[i]; ++j)
		{
			t[j]=0; 
			for (int k=j; k<=c[i]; ++k) add(t[j],1ll*C(k-1,j-1)*sig(k-j)%P*sum[c[i]][k]%P); 
		}
		for (int j=0; j<=curc+c[i]; ++j) g[j]=0; 
		for (int j=0; j<=curc; ++j)
			for (int k=1; k<=c[i]; ++k)
				add(g[j+k],1ll*f[j]*t[k]%P*invf[k]%P); 
		curc+=c[i]; 
		for (int j=0; j<=curc; ++j) swap(f[j],g[j]); 
	}

	ans=0; 
	for (int j=1; j<=sumc; ++j) add(ans,(1ll*f[j]*fact[j-1]%P-(j>1?1ll*g_[j]*fact[j-2]%P:0)+P)%P); 
	printf("%d\n",1ll*ans*sumc%P); 
	fclose(stdin),fclose(stdout); 
	return 0; 
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章