【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; 
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章