题目分析:

一开始以为是直接用指数型生成函数,后来发现复杂度不对,想了一下容斥的方法。

对于有$i$种颜色恰好出现$s$次的情况,利用容斥原理得到方案数为

$$\binom{m}{i}\frac{P_{is}^{n}}{(s!)^i}(\sum_{j=0}^{m-i}(-1)^j\binom{m-i}{j}\frac{P_{js}^{n-is}}{(s!)^j}(m-i-j)^{n-is-js})$$

值得注意的是$n-is-js<0$的时候,后面的式子直接等于$0$,特判一下就行了。

那么答案就等于

$$\sum_{i=0}^{m}w_i\binom{m}{i}\frac{P_{is}^{n}}{(s!)^i}(\sum_{j=0}^{m-i}(-1)^j\binom{m-i}{j}\frac{P_{js}^{n-is}}{(s!)^j}(m-i-j)^{n-is-js})$$

式子看着很长,但其实没啥味道,把组合数和排列数展开,常数项提出来,约分,可以得到上面的式子等价于

$$(n!)*(m!)*\sum_{i=0}^{m}\frac{w_i}{(i!)(s!)^i}(\sum_{j=0}^{m-i}\frac{(-1)^j(m-i-j)^{n-is-js}}{(m-i-j)!j!(n-is-js)!(s!)^j})$$

对于后面的那个求和,使用肉眼观察法,会发现是个关于$j$和$m-i-j$的卷积。因为$m-i-j$的值确定了就意味着$n-is-js$的值也确定了。所以NTT搞出来

时间复杂度$O(nlogn)$

代码:

 #include<bits/stdc++.h>
using namespace std; const int maxn = ;
const int mod = ;
const int gg = ; int n,m,s;
int w[maxn]; int fac[],A[maxn*],B[maxn*]; int fast_pow(int now,int pw){
int ans = ,dt = now,bit = ;
while(bit <= pw){
if(bit &pw){ans = 1ll*ans*dt%mod;}
dt = 1ll*dt*dt%mod; bit<<=;
}
return ans;
} void buildfunc(){
fac[] = ;
for(int i=;i<=max(n,m);i++) fac[i] = 1ll*fac[i-]*i%mod;
for(int i=;i<=m;i++){
A[i] = 1ll*fast_pow(fac[s],i)*fac[i]%mod;
A[i] = fast_pow(A[i],mod-);
if(i&) A[i] = 1ll*(mod-)*A[i]%mod;
}
for(int i=;i<=m;i++){
int z = m-i;
if(n-z*s < ) {B[i] = ;continue;}
int rem = n-z*s;
B[i] = 1ll*fac[i]*fac[rem]%mod;
B[i] = fast_pow(B[i],mod-);
B[i] = 1ll*B[i]*fast_pow(i,rem)%mod;
}
} int ord[maxn*]; void NTT(int *d,int len,int dr){
for(int i=;i<len;i++) if(ord[i] < i) swap(d[i],d[ord[i]]);
for(int i=;i<len;i<<=){
int w = fast_pow(gg,(mod-)/(*i));
if(dr == -) w = fast_pow(w,mod-);
for(int j=;j<len;j+=(i<<)){
for(int k=,wn=;k<i;k++,wn = 1ll*wn*w%mod){
int x = d[j+k],y = 1ll*wn*d[j+k+i]%mod;
d[j+k] = (x+y)%mod;
d[j+k+i] = (x-y+mod)%mod;
}
}
}
if(dr == -){
int iv = fast_pow(len,mod-);
for(int i=;i<len;i++){d[i] = 1ll*d[i]*iv%mod;}
}
} void work(){
buildfunc();
/*int reans = 0;
for(int i=0;i<=m;i++){
int z = 1ll*w[i]*fast_pow(1ll*fac[i]*fast_pow(fac[s],i)%mod,mod-2)%mod;
int np = 0,kp = 0;
for(int j=0;j<m-i;j++){
if(n-i*s-j*s < 0) continue;
int mp = 0;
mp = 1ll*fac[m-i-j]*fac[j]%mod*fac[n-i*s-j*s]%mod*fast_pow(fac[s],j)%mod;
mp = 1ll*fast_pow(mp,mod-2)*fast_pow(m-i-j,n-i*s-j*s)%mod;
if(j & 1) mp = 1ll*(mod-1)*mp%mod;
kp += 1ll*A[j]*B[m-i-j]%mod;
kp %= mod;
np += mp;
np %= mod;
}
reans += 1ll*z*np%mod;
reans %= mod;
}
reans = 1ll*reans*fac[n]%mod*fac[m]%mod;
printf("%d\n",reans);return;*/ int hk = ,pi = ; while(hk <= m+m) hk*=,pi++;
for(int i=;i<hk;i++) ord[i] = (ord[i>>]>>) + ((i&)<<(pi-));
NTT(A,hk,); NTT(B,hk,);
for(int i=;i<hk;i++) A[i] = 1ll*A[i]*B[i]%mod;
NTT(A,hk,-);
int ans = ;
for(int i=;i<=m;i++){
int z = 1ll*fac[m-i]*fast_pow(fac[s],m-i)%mod;
z = 1ll*fast_pow(z,mod-)*w[m-i]%mod;
ans += 1ll*z*A[i]%mod;
ans %= mod;
}
ans = 1ll*ans*fac[n]%mod*fac[m]%mod;
printf("%d\n",ans);
} int main(){
scanf("%d%d%d",&n,&m,&s);
for(int i=;i<=m;i++) scanf("%d",&w[i]);
work();
return ;
}

Luogu4491 [HAOI2018]染色 【容斥原理】【NTT】的更多相关文章

  1. [BZOJ5306] [HAOI2018]染色(容斥原理+NTT)

    [BZOJ5306] [HAOI2018]染色(容斥原理+NTT) 题面 一个长度为 n的序列, 每个位置都可以被染成 m种颜色中的某一种. 如果n个位置中恰好出现了 S次的颜色有 K种, 则小 C ...

  2. 【BZOJ5306】[HAOI2018]染色(NTT)

    [BZOJ5306]染色(NTT) 题面 BZOJ 洛谷 题解 我们只需要考虑每一个\(W[i]\)的贡献就好了 令\(lim=min(M,\frac{N}{S})\) 那么,开始考虑每一个\(W[i ...

  3. [HAOI2018][bzoj5306] 染色 [容斥原理+NTT]

    题面 传送门 思路 这道题的核心在于"恰好有$k$种颜色占了恰好$s$个格子" 这些"恰好",引导我们去思考,怎么求出总的方案数呢? 分开考虑 考虑把恰好有$s ...

  4. 【题解】[HAOI2018]染色(NTT+容斥/二项式反演)

    [题解][HAOI2018]染色(NTT+容斥/二项式反演) 可以直接写出式子: \[ f(x)={m \choose x}n!{(\dfrac 1 {(Sx)!})}^x(m-x)^{n-Sx}\d ...

  5. BZOJ 5306 [HAOI2018] 染色

    BZOJ 5306 [HAOI2018] 染色 首先,求出$N$个位置,出现次数恰好为$S$的颜色至少有$K$种. 方案数显然为$a_i=\frac{n!\times (m-i)^{m-i\times ...

  6. 【BZOJ5306】 [Haoi2018]染色

    BZOJ5306 [Haoi2018]染色 Solution xzz的博客 代码实现 #include<stdio.h> #include<stdlib.h> #include ...

  7. [洛谷P4491] [HAOI2018]染色

    洛谷题目链接:[HAOI2018]染色 题目背景 HAOI2018 Round2 第二题 题目描述 为了报答小 C 的苹果, 小 G 打算送给热爱美术的小 C 一块画布, 这块画布可 以抽象为一个长度 ...

  8. 【LG4491】[HAOI2018]染色

    [LG4491][HAOI2018]染色 题面 洛谷 题解 颜色的数量不超过\(lim=min(m,\frac nS)\) 考虑容斥,计算恰好出现\(S\)次的颜色至少\(i\)种的方案数\(f[i] ...

  9. 【bzoj3456】城市规划 容斥原理+NTT+多项式求逆

    题目描述 求出n个点的简单(无重边无自环)无向连通图数目mod 1004535809(479 * 2 ^ 21 + 1). 输入 仅一行一个整数n(<=130000) 输出 仅一行一个整数, 为 ...

随机推荐

  1. Centos7+nginx+keepalived集群及双主架构案例

    目录简介 一.简介 二.部署nginx+keepalived 集群 三.部署nginx+keepalived双主架构 四.高可用之调用辅助脚本进行资源监控,并根据监控的结果状态实现动态调整 一.简介 ...

  2. DSAPI TreeView节点增删简化操作

    将一行或多行字符串添加到TreeView控件. 函数: 控件.TreeView控件.添加路径节点到TreeView(要添加节点的TreeView控件,字符串或字符串数组) 示例:将一个多行文本添加到T ...

  3. 校园生活app结对开发第二天

    昨天进行了android studio的安装与配置遇到很多问题,在gradel处遇到很多问题,安装版本错误等等,在百度和书籍的帮助下成功安装 今天要做登陆界面开发

  4. java面试记录

    怎么确保一个集合不能被修改   ArrayList<String> list = new ArrayList<>();list.add("x");Colle ...

  5. Java运行时环境---内存划分

    背景:听说Java运行时环境的内存划分是挺进BAT的必经之路. 内存划分: Java程序内存的划分是交由JVM执行的,而不像C语言那样需要程序员自己买单(C语言需要程序员为每一个new操作去配对del ...

  6. wordpress主题

    1.创建wordpress主题:在themes文件下建立新主题black文件夹 2.在black文件夹中放入index.php和style.css文件,其中index对style.css文件的引用 & ...

  7. Nginx支持 React browser router

    修改nginx配置文件,添加try_file配置如下,即可实现对 React browser router 的支持. location / { root /var/www/mysite; try_fi ...

  8. 【NodeJS】基础知识

    nodejs基础 nodejs允许自己封装模块,使得编写程序可以模块化,便于维护整理.在一个js文件中写完封装的函数或对象后,可以使用exports或module.exports来将模块中的函数暴露给 ...

  9. 关于boostrap的modal隐藏问题(前端框架)

    Modal(模态框) 首先,外引boostrap和Jquery的文件环境: <link rel="stylesheet" href="https://cdn.sta ...

  10. Numpy库的学习(三)

    今天我们继续学习一下Numpy库的学习 废话不多说 ,开始讲 比如我们现在想创建一个0-14这样一个15位的数组 可以直接写,但是很麻烦,Numpy中就给我们了一个方便创建的方法 numpy中有一个a ...