[NTT][组合]P4491 [HAOI2018]染色
题面
https://www.luogu.com.cn/problem/P4491
有 n 个空格,每个空格都可以填 m 种颜色,当恰好有 k 种颜色出现了 S 次时,权值为 w[k] ,求所有方案的权值和
分析
推导起来特别爽的题
首先 k 的最大值
设当前至少有 i 种颜色出现了 S 次的方案数为
则选择 i 种颜色是
选出放这 i 种颜色的位置是
i 种颜色任意排列,除去同色内部排列是
最后剩下位置任意选非该 i 种颜色是
则
考虑容斥,则有
其中 表示至少有 i 种颜色在至少有 j 种里面被计算了这么多次(二项式定理)
拆组合数
将无关项移项,相近项合并
然后设 ,
原 ans 后式为 ,仍不是卷积形式
将 系数高次项与低次项反转,则
为卷积形式
最后计算的时候取卷积后的函数第 K-i 位系数作为结果,即
代码

#include <iostream> #include <cstdio> using namespace std; typedef long long ll; const ll P=1004535809ll; const int N=131072; const int M=1e7+10; int n,m,K,S,bit; ll fact[M],inv[M],f[N<<2],g[N<<2],w[N],ref[N<<2],ans; ll Pow(ll x,ll y) {ll ans=1;for (;y;y>>=1,x=x*x%P) if (y&1) ans=ans*x%P;return ans;} ll C(int n,int m ) {return fact[n]*inv[m]%P*inv[n-m]%P;} void Get_Ref(int bit,int mxb) {for (int i=1;i<mxb;i++) ref[i]=(ref[i>>1]>>1)|((i&1)<<bit-1);} void NTT(ll *a,int n,int idft) { for (int i=0;i<n;i++) if (ref[i]>i) swap(a[ref[i]],a[i]); for (int mlen=1;mlen<n;mlen<<=1) { ll g1=Pow(3,(P-1)/(mlen<<1)); if (idft<0) g1=Pow(g1,P-2); for (int l=0,len=mlen<<1;l<n;l+=len) { ll gk=1; for (int i=l;i<l+mlen;i++) { ll x=a[i],y=(a[i+mlen]*gk)%P; a[i]=(x+y)%P;a[i+mlen]=(x-y+P)%P; (gk*=g1)%=P; } } } if (idft<0) { ll inv=Pow(n,P-2); for (int i=0;i<n;i++) (a[i]*=inv)%=P; } } int main() { scanf("%d%d%d",&n,&m,&S);K=min(n/S,m); for (int i=0;i<=m;i++) scanf("%lld",&w[i]); fact[0]=1;for (int i=1;i<=max(n,m);i++) fact[i]=fact[i-1]*i%P; inv[max(n,m)]=Pow(fact[max(n,m)],P-2);for (int i=max(n,m)-1;~i;i--) inv[i]=inv[i+1]*(i+1)%P; for (int i=0;i<=K;i++) f[i]=(i&1?P-1:1)*inv[i]%P,g[K-i]=C(m,i)*C(n,i*S)%P*fact[i*S]%P*Pow(inv[S],i)%P*Pow(m-i,n-i*S)%P*fact[i]%P; for (int i=K;i;i>>=1,bit++);bit++; Get_Ref(bit,1<<bit); NTT(f,1<<bit,1);NTT(g,1<<bit,1); for (int i=0;i<(1<<bit);i++) (f[i]*=g[i])%=P; NTT(f,1<<bit,-1); for (int i=0;i<=K-i;i++) swap(f[i],f[K-i]); for (int i=0;i<=K;i++) (ans+=w[i]*f[i]%P*inv[i]%P)%=P; printf("%lld\n",ans); }
在日渐沉没的世界里,我发现了你。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构