HAOI2018 染色 NTT,組合計數

2022-06-07 01:24:11 字數 1236 閱讀 5287

對乙個長度為 \(n\) 的序列進行染色,有 \(m\) 種顏色。對一種方案,如果恰好出現 \(s\) 次的顏色總數為 \(k\),則得分為 \(w_k\),求所有染色方案得分的總和。\(n\leq 10^7,m\leq 10^5,s \leq 150\)

最大有效顏色數為 \(lim=\min(m,n/s)\)

設恰好出現 \(s\) 次的顏色有至少 \(i\) 種的方案數字 \(f[i]\),則選出這 \(i\) 種顏色,並給他們分配位置,剩下的相互獨立填入即可,即

\[f[i]=c_m^i \frac(m-i)^

\]設 \(ans[i]\) 表示出現 \(s\) 次的顏色恰好有 \(i\) 種的方案數,由容斥原理,

\[ans[i]=\sum_^ (-1)^ c_j^i f[j]

\]為了方便做卷積,變形為

\[ans[i]\cdot i!=\sum_^ \frac} f[j]\cdot j!

\]不妨令

\[a[k]=\frac \quad \quad b[k]=f[k]\cdot k!

\]那麼卷積就可以描述為

\[c[i]=\sum_ a[k]b[j]

\]很自然地,設 \(d[k]=a[lim-k]\),則

\[c[i]=\sum_ d[lim-k]b[j]=\sum_ d[u]b[j]=\sum_b[j]d[k]

\]答案就是

\[\sum_^ ans[i]\cdot w_i

\]

#include using namespace std;

#define pw(n) (1<>1]>>1)|((i&1)

int fastpow(int a,int b)

return ans;

}void ntt(int *s,int op)

void load(int *x,int n)

poly pb,pd;

pb.load(b,lim+1);

pd.load(d,lim+1);

poly pc=pb*pd;

int ans=0;

for(int i=0;i<=lim;i++) ans+=pc.a[i+lim]*inv(frac[i])%mod*w[i]%mod, ans+=mod, ans%=mod;

cout<

}

HAOI 2018 染色(容斥 NTT)

設 f k 為強制選擇 k 個顏色出現 s 種,其餘任取的方案數。則有 f k m k 不難看出,這個方案可能包括了超過 k 種顏色,也有重複的方案,所以恰有 k 個顏色出現 s 種的方案 ans k 滿足 ans k sum 1 f i 最終化簡得到 ans k sum i f i cdot ov...

HAOI2018 簡要題解

以前做過的 haoi2018 染色 haoi2018 蘋果樹暫時不更 haoi2018 字串覆蓋 已經棄療了。總體難度 medium 偏 easy,但是 luogu4495 haoi2018 奇怪的揹包 想不到是真的腦抽。可以在 找到。小 c 和小 g 經常在一起研究搏弈論問題,有一天他們想到了這樣...

HAOI2018 蘋果樹(組合數學)

首先有個很奇妙而且很有用的性質 每個二叉樹對應唯一的中序遍歷,然後每個二叉樹出現概率相同。所以n個節點的二叉樹形態是n 種 題目中說了 n 已經是提示了 對每種方案求和即可得到期望。令f i 表示i個節點的子樹,根深度為1時,所有點的期望深度之和乘i 的值,令g i 表示i個節點的子樹,期望兩兩路徑...