题目分析:

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

对于有$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. CSS超出省略号样式

    overflow:hidden;text-overflow:ellipsis;-wekit-line-clamp:3;display:-webkit-box;-webkit-box-orient:ve ...

  2. mybatis bug之org.apache.ibatis.exceptions.PersistenceException:

    详细报错信息: org.apache.ibatis.exceptions.PersistenceException: ### Error querying database. Cause: java. ...

  3. Ubuntu16.04安装RealSense SR300驱动

    原文链接 https://blog.csdn.net/u013401766/article/details/78472285 第一步:CMake 3.14.0 安装 1)下载cmake-3.14.1. ...

  4. (爬虫)requests库

    一.requests库简介 urllib库和request库的作用一样,都是服务器发起请求数据,但是requests库比urllib库用起来更方便,它的接口更简单,选用哪种库看自己. 如果没有安装过这 ...

  5. pyspider安装提示:got an unexpected keyword argument 'io_loop'的解决办法

    此问题解决办法学习自pyspider的github的issues 原地址:https://github.com/binux/pyspider/issues/771 解决方法: 由于最新版的Tornad ...

  6. linux 命令基础大全

    pwd:显示当前路径 cd :切换目录 用法:cd cd ../ 切换到上级目录 cd /   切换到根目录 cd ~  (或只有cd )切换到当前用户主目录(home底下以用户名命名的文件夹) /r ...

  7. zabbix配置邮件告警

    1.安装邮件服务 yum -y install mailx @qq.com #发邮件测试 2.添加报警媒介 输入接收告警邮件的邮箱 3.配置SMTP服务端 使用本机作为SMTP服务器 4.创建触发器 ...

  8. 基于gdal的格网插值

    格网插值就是使用离散的数据点创建一个栅格图像的过程.通常情况下,有一系列研究区域的离散点,如果我们想将这些点转换为规则的网格数据来进行进一步的处理,或者和其他网格数据进行合并 等处理,就需要使用格网插 ...

  9. Azure按订阅,资源组,资源类型导出所有资源powershell命令

    一般可以借助powershell命令来读取资源:例如:1, 读取某个订阅下的资源:$subscriptionID = "xxxxxxxx"Set-AzureRmContext $s ...

  10. Linux:Day18(下) Bind9

    子域授权:每个域的名称服务器,都是通过其上级名称服务器在解析库中进行授权. 类似根域授权tld: .com IN NS ns1.com. .com IN NS ns1.com. ns1.com IN ...