题目分析:

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

对于有$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. 【转载】假设有以下代码 String s = “hello”; 阿里巴巴笔试题

    原文链接点这里 equals 源码如下: 分析: //true equal用于比较两个对象的值是否相同,和内存地址无关

  2. Go channel实现源码分析

    go通道基于go的并发调度实现,本身并不复杂,go并发调度请看我的这篇文章:go并发调度原理学习 1.channel数据结构 type hchan struct { qcount uint // 缓冲 ...

  3. 基于python开发的股市行情看板

    个人博客: https://mypython.me 近期股市又骚动起来,回忆起昔日炒股经历,历历在目,悲惨经历让人黯然神伤,去年共投入4000元入市,最后仅剩1000多,无奈闭关修炼,忘记股市,全身心 ...

  4. Jmeter、Java当double显示的数字过长时取消科学计数法显示

    今日,由于项目需要,使用Jmeter发送查询账户并不保存余额,经过交易后,进行运算后再次比对余额. 实施过程中获取了余额字段并赋值给一个double变量.变量进行运算后再与交易后的账户余额进行比对.这 ...

  5. Delphi 字符串转日期,强大到窒息,VarToDateTime 解决了 困扰很久的小问题

    procedure THRForm.Button1Click(Sender: TObject); var D:TDateTime; s:string; begin D:=VarToDateTime(' ...

  6. jqery autocomplete 动态传递参数的问题

    今天弄一个autocomplete 向后后台动态传递参数的问题 老的写法: params: { "saleid": $("#divSalesman input[field ...

  7. SQL优化小技巧

    我们要做到不但会写SQL,还要做到写出性能优良的SQL语句. 1.使用表的别名(Alias): 当在SQL语句中连接多个表时, 请使用表的别名并把别名前缀于每个Column上.这样一来,就可以减少解析 ...

  8. .net core 命令行(仅作记录)

    命令大全:dotnet 命令 创建NuGet包:如何使用 .NET Core 命令行接口 (CLI) 工具创建 NuGet 包

  9. js坚持不懈之14:不要在文档加载之后使用 document.write()示例

    在看w3school的JavaScript教程时,关于文档输出流中有这么一句话:绝不要在文档加载之后使用 document.write().这会覆盖该文档. 不太明白什么意思,找了一个例子: < ...

  10. python3 员工信息表

    这是最后一条NLP了......来吧 十二,动机和情绪总不会错,只是行为没有效果而已 动机在潜意识里,总是正面的.潜意识从来不会伤害自己,只会误会的以为某行为可以满足该动机,而又不知道有其他做法的可能 ...