1. 程式人生 > 實用技巧 >聯合省選 2020 A」組合數問題

聯合省選 2020 A」組合數問題

「聯合省選 2020 A」組合數問題

題意:

\(\begin{aligned}\sum _{k=0}^nf(k)\cdot x^k\cdot C(n,k)\end{aligned}\)

顯然要對於\(f(k)\)的每一項考慮,第\(i\)項的貢獻

\(a_i\begin{aligned}\sum _{k=0}^nk^i\cdot x^k\cdot C(n,k)\end{aligned}\)

通用的\(O(m^2)\)

後面的這個式子,考慮它的組合意義,假設當前有\(n\)個格子,每個格子被染了\([0,x]\)的顏色

\(x^k\cdot C(n,k)\)即列舉有\(k\)個格子塗了\([1,x]\)

的顏色,剩下塗了\(0\)的顏色

\(k^i\)的組合意義即可重複地選了\(i\)次,每次選出的都是在\([1,x]\)顏色的格子的方案數

那麼問題可以轉化為強制每一次被訪問的格子都是\([1,x]\),其他的格子隨便塗\([0,x]\)

問題在於每次被訪問的格子會重複,於是可以想到一個簡單的轉化,求出\(i\)次訪問了\(j\)不同位置的方案數

即斯特林數\(S(i,j)\),可以得到的是

\(\begin{aligned}\sum _{k=0}^nk^i\cdot x^k\cdot C(n,k)=\sum_{j=0}^iS(i,j)\cdot \frac{n!}{(n-j)!}\cdot x^j(x+1)^{n-j}\end{aligned}\)

實際上可以在\(O(m^2)\)遞推斯特林數時就把\(\frac{n!}{(n-j)!}\)加入權值,\(x^j(x+1)^{n-j}\)可以預處理出來

因此總複雜度就是\(O(m^2)\)

#include<cstdio>
long long i,j,n,m,P,x,y,F[1010],Pow[1010],r,ans;
int qpow(int x,int k) { 
	for(r=1;k;k>>=1,x=1ll*x*x%P) if(k&1) r=r*x%P; 
	return r; 
}
int main(){
	freopen("problem.in","r",stdin),freopen("problem.out","w",stdout);
	scanf("%lld%lld%lld%lld%lld",&n,&x,&P,&m,&y),F[0]=1,ans=qpow(x+1,n)*y%P;
	for(int i=0;i<=m;++i) Pow[i]=1ll*qpow(x,i)*qpow(x+1,n-i)%P;
	for(i=1;i<=m;++i) {
		long long res=0;
		for(j=i,scanf("%lld",&y);~j;--j) {
			F[j]=(F[j]*j+(j?F[j-1]*(n-j+1):0))%P; // 類似斯特林數的遞推
			res=(res+F[j]*Pow[j])%P;
		}
		ans=(ans+res*y)%P;
	}
	printf("%lld",ans);
}

特殊的\(O(m\log m)\)

(注意以下僅限於口胡!)

假設可以把\(f(k)\)轉化為下降冪多項式,依然列舉每一項考慮,那麼每次要求的就是

\(\begin{aligned}\sum _{k=0}^nk^{\underline i}\cdot x^k\cdot C(n,k)=i!\sum _{k=0}^nC(k,i)\cdot x^k\cdot C(n,k)\end{aligned}\)

依然考慮組合意義

\(x^k\cdot C(n,k)\)即列舉有\(k\)個格子塗了\([1,x]\)的顏色,剩下塗了\(0\)的顏色

\(C(k,i)\)的組合意義不可重複地選了\(i\)次,每次選出的都是在\([1,x]\)顏色的格子的方案數

那麼問題可以轉化為強制每一次被訪問的格子都是\([1,x]\),其他的格子隨便塗\([0,x]\)

\(\begin{aligned}\sum _{k=0}^nk^{\underline i}\cdot x^k\cdot C(n,k)=i!\cdot C(n,i)\cdot x^i\cdot (x+1)^{n-i}\end{aligned}\)

眾所周知,求解下降冪多項式需要求\(f(k)\)\(\begin{aligned} e^x=\sum_0^{\infty}\frac{x^i}{i!}\end{aligned}\)的卷積

最後的答案就是 \(\begin{aligned} \sum_{i=0}^m i! \cdot C(n,i) \cdot x^i \cdot (x+1)^{n-i} [k^i](f(k)e^k) \end{aligned}\) (式子應該沒有問題,但是下面都是口胡)

然而對於非質數的\(P\),我們求不出\(i!\)的逆元

(比較智障的搞法就是每次乘法都存下\(P\)的每個質因數個數,這樣,做乘法的複雜度是\(\log P\),但是不知道最後做出的答案是不是能保證因數個數\(\ge 0\))

對於\(P\)為質數的情況,做\(\text{MTT}\)的複雜度是\(O(m\log m)\)