Luogu4491 [HAOI2018]染色 【容斥原理】【NTT】
题目分析:
一开始以为是直接用指数型生成函数,后来发现复杂度不对,想了一下容斥的方法。
对于有$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】的更多相关文章
- [BZOJ5306] [HAOI2018]染色(容斥原理+NTT)
[BZOJ5306] [HAOI2018]染色(容斥原理+NTT) 题面 一个长度为 n的序列, 每个位置都可以被染成 m种颜色中的某一种. 如果n个位置中恰好出现了 S次的颜色有 K种, 则小 C ...
- 【BZOJ5306】[HAOI2018]染色(NTT)
[BZOJ5306]染色(NTT) 题面 BZOJ 洛谷 题解 我们只需要考虑每一个\(W[i]\)的贡献就好了 令\(lim=min(M,\frac{N}{S})\) 那么,开始考虑每一个\(W[i ...
- [HAOI2018][bzoj5306] 染色 [容斥原理+NTT]
题面 传送门 思路 这道题的核心在于"恰好有$k$种颜色占了恰好$s$个格子" 这些"恰好",引导我们去思考,怎么求出总的方案数呢? 分开考虑 考虑把恰好有$s ...
- 【题解】[HAOI2018]染色(NTT+容斥/二项式反演)
[题解][HAOI2018]染色(NTT+容斥/二项式反演) 可以直接写出式子: \[ f(x)={m \choose x}n!{(\dfrac 1 {(Sx)!})}^x(m-x)^{n-Sx}\d ...
- BZOJ 5306 [HAOI2018] 染色
BZOJ 5306 [HAOI2018] 染色 首先,求出$N$个位置,出现次数恰好为$S$的颜色至少有$K$种. 方案数显然为$a_i=\frac{n!\times (m-i)^{m-i\times ...
- 【BZOJ5306】 [Haoi2018]染色
BZOJ5306 [Haoi2018]染色 Solution xzz的博客 代码实现 #include<stdio.h> #include<stdlib.h> #include ...
- [洛谷P4491] [HAOI2018]染色
洛谷题目链接:[HAOI2018]染色 题目背景 HAOI2018 Round2 第二题 题目描述 为了报答小 C 的苹果, 小 G 打算送给热爱美术的小 C 一块画布, 这块画布可 以抽象为一个长度 ...
- 【LG4491】[HAOI2018]染色
[LG4491][HAOI2018]染色 题面 洛谷 题解 颜色的数量不超过\(lim=min(m,\frac nS)\) 考虑容斥,计算恰好出现\(S\)次的颜色至少\(i\)种的方案数\(f[i] ...
- 【bzoj3456】城市规划 容斥原理+NTT+多项式求逆
题目描述 求出n个点的简单(无重边无自环)无向连通图数目mod 1004535809(479 * 2 ^ 21 + 1). 输入 仅一行一个整数n(<=130000) 输出 仅一行一个整数, 为 ...
随机推荐
- .NET CAD二次开发学习 直线画矩形并转换成组
主要代码: using System;using System.Collections.Generic;using System.Linq;using System.Text;using System ...
- 关于Exceptionless的使用注意
大家都应该比较熟悉NLOG,我们知道log4net和nlog,也有其它的记日志框架.目前我们的生产环境使用nlog,而且对Exceptionless的对接也是无缝的.可能有人会问为什么不用ELK,主要 ...
- OPP的三大特征之封装总结
'''封装: 1.什么是封装? 封装是把什么东西装到容器中,再封闭起来 与隐藏有相似之处,但不是单纯的隐藏 官方解释:封装是指对外部隐藏实现细节,并提供简单的使用接口 封装的好处: 1.提高安全性 2 ...
- Web后端 JAVAWeb面试考查知识点
面试知识点:1:简单讲一下Java的跨平台原理答:由于非跨平台的情况下,对于不同的操作系统,那么就需要开发几套不同程序代码.为了解决这个问题,java通过不同系统,不同版本,不同位数的JVM来屏蔽不同 ...
- Handler,Looper,MessageQueue流程梳理
目的:handle的出现主要是为了解决线程间通讯. 举个例子,android是不允许在主线程中访问网络,因为这样会阻塞主线程,影响性能,所以访问网络都是放在子线程中执行,对于网络返回的结果则需要显示在 ...
- Chromium被用于Microsoft Edge与ChakraCore的未来【译】
注:英语不好,力求大概能懂.持笔人是:Limin Zhu,好像是中国人,但是没有提供中文版本. 大家好,ChakraCore的朋友们: 昨天,微软公布,Microsoft Edge桌面浏览器采用Chr ...
- MPP-编码示例
了解MPP的基本功能后,接下来具体分析编码的代码.首先把编码的代码提取出来,方便以后的使用. 完整的编码代码如下,相比较给出的示例代码,做了一些改动,输入的指令全部去除,将函数入口改为利用OpenCV ...
- extjs 倒计时
var interval = (new Date(selection[0].data.dealLimitTime).getTime() - new Date().getTime()) / 1000; ...
- 神经网络MPLClassifier分类
代码: # -*- coding: utf-8 -*- """ Created on Fri Aug 24 14:38:56 2018 @author: zhen &qu ...
- PowerShell或命令行运行javac xx.java提示“编码GBK的不可映射字符”
由于JDK是国际版的,我们在用javac编译时,编译程序首先会获得我们操作系统默认采用的编码格式(GBK),然后JDK就把Java源文件从GBK编码格式转换为Java内部默认的Unicode格式放入内 ...