[省選聯考 2020 A 卷] 組合數問題


前言:

 

這是我退役賽省選中唯一一道答得令自己滿意的題目。

也就是

$skyh:$難道你沒$AC$

的那道題。

這道題我想了大概二十多分鍾。覺得不是很簡單。

然而考后出來才發現,大神們都是用數學推導$AC$的這道題。

而我,眾所周知,退役在即的我菜的不行,自然不會數學推導。

所以說如果你什么也不會,你怎么做這道題呢?

於是這里有一個菜菜的組合含義理解方法。(幾乎)沒有任何數學推導。

(可能和luogu的某些題解撞了?不知道我沒看)

雖然時間復雜度顯然不優是$O(m^2log)$的但是應該比較好懂……(考場上犯傻了其實可以簡單優化成$O(m^2)$)

於是打算做一個大膽的嘗試:能不能給學弟(妹)們講懂。

沒關系看不懂就證明我果然還是太菜了QAQ

 

$Description:$

求$\sum\limits_{k=0}^{n} \binom{n}{k} x^k f(k)$其中$f(x)=\sum\limits_{i=0}^{m} a_ix^i$

15%:$n\le 10^3$

+25%:$m=0$

+20%:$x=1$

100%:$m\le 10^3,others \le 10^9$

(只給出了我用到的部分分)

 

$n \le 10^3:$

你可以用多項式多點求值求出所有$f$的值然后……編不下去了。

(真慶幸沒單獨提出來一個$n \le 5 \times 10^4$的部分分)

 

$m=0:$

也就是說$f(x)$是一個與$x$無關的常數。不妨設其為$1$最后乘上常數倍。

式子的形式是:$\sum\limits_{k=0}^{n} x^k \binom{n}{k}$

考慮實際含義:我們要對於所有$k$求出,從$n$個物品里選出$k$個,每種選法的貢獻是$x^k$

於是我們可以對於這$n$個物品考慮:每個物品被選中就貢獻$x$,沒被選中貢獻$1$,一種選法的貢獻就是所有物品乘起來。

你要求出的是所有選法的貢獻和,而物品之間是獨立的,每種物品都會作為$1,x$出現各一次。

所以其實就是$(1+x)^n$。把這個東西展開,就是乘法分配律,就得到的是所有方案的和。

(然而寫出啦我才知道,這不就是個二項式定理嗎我考場上為啥要這么弱智啊)

 

$x=1:$

也就是說$x^k$那一項消失了。剩下的形式是$\sum\limits_{k=0}^{n} f(k) \binom{n}{k}$

你自然拿多項式沒什么辦法,所以把它展開:

$\sum\limits_{i=0}^{m} a_i \sum\limits_{k=0}^{n} k^i \binom{n}{k}$

外邊的這個$i$大力枚舉。考慮內部的組合含義:

我要從$n$個物品里選出$k$個,然后貢獻是$k^i$($i$是枚舉的所以已知,可以視為常數)

這個$k^i$好像有點難辦,怎么去理解?就是從$k$個物品里可重復地選擇$i$次啊。

所以我們就是要從$n$個數里選$k$個,再在這$k$個里可重復欽定$i$次。

卡住了。於是我們改變枚舉的東西:我們嘗試去枚舉一下這$k$個物品里有多少個物品被至少欽定過一次,設為$j$。

(因為你是可重復選擇$i$次,所以枚舉上屆就是$i$,$i \le m$復雜度沒問題)

那么我們從$n$個物品里選擇$j$個作為被欽定過地元素:這是$\binom{n}{j}$

那么你要把$i$次選擇分配給這$j$個元素,且每個元素非空。這顯然是個第二類斯特林數。

(啊學弟們是不是不知道什么是斯特林數啊,那我失敗了啊,我好菜啊)

然而其實只是一個$O(n^2)$遞推的東西:$\begin{Bmatrix} n \\ k \end{Bmatrix}$表示將$n$個帶編號的球扔進$k$個不帶標號桶里且每個桶都有球的方案數。

然而在本道題當中,根據題目含義,桶是帶標號的,所以還要乘上一個階乘。這里的階乘和上面的組合數形成下降冪$n^{\underline{j}}$

(這個東西學弟們可以當成一個dp來做)

同時你還要考慮原來$n$個里選$k$個的過程:我們知道我們所欽定的$j$個元素一定被選了,沒欽定的$n-j$個元素選不選都可以,總方案數是$2^{n-j}$

所以總的方案數是$\sum\limits_{i=0}^{m} a_i \sum\limits_{j=0}^{i} n^{\underline{j}} 2^{n-j} \begin{Bmatrix} i \\ j \end{Bmatrix}$

兩層循環暴力枚舉完事。組合數的話因為$n$是確定的所以直接搞一個下降冪就好了。

 

無特殊限制:

$\sum\limits_{k=0}^{n} \binom{n}{k} x^k f(k)$

和上一個部分分一樣先拆$f$得到$\sum\limits_{i=0}^{m} a_i \sum\limits_{k=0}^{n} k^i \binom{n}{k} x^k $

和上一個部分分一樣我們改變含義去枚舉$j$表示被欽定的元素個數,然后接着分析:

其實除了$2^{n-j}$那部分以外,其余都和上面一樣可以得到$n^{\underline{j}} \begin{Bmatrix} i \\ j \end{Bmatrix}$

然后因為$x$不再是$1$所以我們不是要計數方案,而是統計方案的貢獻和。其中的貢獻和第一檔部分分一樣,選中是$x$沒選中是$1$

然后就比較簡單了:你欽定的$j$個都一定被選中了是$x^j$,剩下的選不選都行,考慮所有情況就是$(x+1)^{n-j}$

最后的答案是$\sum\limits_{i=0}^{m} a_i \sum\limits_{j=0}^{i} \begin{Bmatrix} i \\ j \end{Bmatrix} x^j (x+1)^{n-j} n^{\underline{j}}$

我個弱智只預處理了斯特林數和下降冪,剩下的快速冪,$O(m^2log)$

然而快速冪只用到了$x^{a},(x+1)^{n-a}$。$a \le m$。所以說也可以簡單預處理。復雜度下降到$O(m^2)$

 

我相信學弟們一定沒聽懂。我太菜了

我就是來騙閱讀量的

 

其實這道題這么順下來部分分給的真棒啊……我喜歡。雖然並無卵用

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int $=1003;
 4 int st[$][$],mod,n,m,x,a[$],dpw[$],ans;
 5 int qp(int b,int t,int a=1){for(;t;t>>=1,b=1ll*b*b%mod)if(t&1)a=1ll*a*b%mod;return a;}
 6 int main(){
 7     scanf("%d%d%d%d",&n,&x,&mod,&m); st[0][0]=1;
 8     for(int i=1;i<=m;++i)for(int j=1;j<=i;++j)st[i][j]=(1ll*st[i-1][j]*j+st[i-1][j-1])%mod;
 9     for(int i=0;i<=m;++i)scanf("%d",&a[i]);
10     for(int i=dpw[0]=1;i<=m;++i)dpw[i]=dpw[i-1]*(n-i+1ll)%mod;
11     for(int i=0;i<=m;++i)for(int j=0;j<=i;++j)ans=(ans+1ll*a[i]*st[i][j]%mod*qp(x,j)%mod*qp(x+1,n-j)%mod*dpw[j])%mod;
12     cout<<ans<<endl;
13 }
令人快活的13行AC代碼

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM