對乙個長度為 \(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個節點的子樹,期望兩兩路徑...