【题解】[HAOI2018]染色(NTT+容斥/二项式反演)
【题解】[HAOI2018]染色(NTT+容斥/二项式反演)
可以直接写出式子:
\]
\(f(x)\) 钦定有\(x\)种颜色出现了恰好\(S\)的方案
然后推一下恰好有\(x\)种颜色出现了恰好\(S\)次的方案\(g(x)\) 。推导在下下面。
最后的答案是\(\sum w_i g(i)\)
推导:
显然颜色种类不会超过\(L=\lfloor \dfrac n s \rfloor\) ,然后限制一下\(L\le n ,L\le m\)
先有关系式
\]
(恰好出现多次,会有\({i\choose x}\)被钦定的可能。)
再容斥(或者叫二项式反演?)得到
\]
解释一波这个容斥的含义
由于对于每个有\(u\)种颜色出现\(S\)的方案,有三种状态:
当\(u\)少于目标\(x\)时:在\(f(x)\)中被计算了\(0\)次。
当\(u\)等于目标\(x\)时:在\(f(x)\)中只被计算了\(1\)次。
当\(u\)大于目标\(x\)时:
考虑这个方案,在\(f(x)\)到\(f(u)\)之中分别计算了
\[{u\choose x},{u\choose x+1},\dots{u\choose u}
\]次,很像一个二项式定理展开。
然后我们考虑一下\({x+i\choose x}f(x+i)\)的情况
\[{u\choose x}{x\choose x},{u\choose x+1}{x+1\choose x},\dots{u\choose u}{u\choose x}
\]晓得一个公式,那就是
\[{a\choose b}{b\choose c}={a\choose c}{a-c\choose b-c}
\]用这个公式化简一下上面那个式子
\[\sum_{i=0}^{u-x}{u\choose x}{u-x\choose i}
\]好家伙,右边就是一个二项式定理啊!
继续化简
\[={u\choose x}\sum_{i=0}^{u-x}{u-x\choose i}={u\choose x}(1+1)^{u-x}
\]现在我们要让等式右边变成
\[0={u\choose x}\times 0={u\choose x}(1-1)^{u-x}
\]我们在\(f(i)\)前面乘上一个容斥系数即可。此时,\(u\le x\)的情况不受影响。
故
\[\sum_{i=x}^L (-1)^{i-x}{i\choose x}f(i)=g(x)
\]
然后我们把\(g(x)\)的式子化简一下
\\
\therefore x!g(x)=\sum_{i=x}^L\dfrac {(-1)^{i-x}}{(i-x)!}\times i!f(i)
\]
拿出来
\]
我们把f数组带i!给reverse一下
现在问题就是快速求\(x!g(x)\)了,考虑到\(NTT\)实际上就是求\(c_i=\sum_{k+j=i}a_kb_j\)。套进NTT就好了。注意到这不是标准的NTT式子,所以个别地方微调。
人丑代码丑,不保证所有时刻可以AC
//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; typedef long long ll;
inline int qr(){
register int ret=0,f=0;
register char c=getchar();
while(c<48||c>57)f|=c==45,c=getchar();
while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
return f?-ret:ret;
}
namespace poly{
const int maxn=1<<18|1;
int a[maxn],b[maxn],A[maxn],B[maxn],r[maxn];
int savlen;
inline void getr(int len){
if(len==savlen)return;
int cnt=0;
for(register int t=1;t<len;t<<=1)++cnt;
for(register int t=1;t<len;++t)
r[t]=r[t>>1]>>1|(t&1)<<cnt>>1;
}
const int mod=1004535809;
const int g=3;
inline int ksm(int base,int p){
register int ret=1;
for(base%=mod;p;p>>=1,base=1ll*base*base%mod)
if(p&1) ret=1ll*ret*base%mod;
return ret;
}
const int gi=ksm(3,mod-2);
inline void NTT(int*a,const int&len,const int&tag){
getr(len);
for(register int t=1;t<len;++t)
if(r[t]>t) swap(a[t],a[r[t]]);
int *a1,*a0,s=g;
if(tag!=1) s=gi;
for(register int t=1,wn;t<len;t<<=1){
wn=ksm(s,(mod-1)/(t<<1));
for(register int i=0;i<len;i+=t<<1){
a1=(a0=a+i)+t;
for(register int j=0,w=1,tm;j<t;++j,++a1,++a0,w=1ll*w*wn%mod){
tm=1ll**a1*w%mod;
*a1=(*a0-tm)%mod;
*a0=(*a0+tm)%mod;
if(*a1<0)*a1+=mod;
}
}
}
if(tag!=1)
for(register int t=0,in=ksm(len,mod-2);t<len;++t)
a[t]=1ll*a[t]*in%mod;
}
void INV(int*a,int*b,const int&len){
if(len==1){b[0]=ksm(a[0],mod-2);return;}
INV(a,b,len>>1);
for(register int t=0;t<len;++t) A[t]=a[t],B[t]=b[t];
NTT(A,len<<1,1);NTT(B,len<<1,1);
for(register int t=0,w=len<<1;t<w;++t) A[t]=1ll*A[t]*B[t]%mod*B[t]%mod;
NTT(A,len<<1,-1);
for(register int t=0;t<len;++t) b[t]=((b[t]+b[t])%mod-A[t]+mod)%mod;
}
}
using poly::NTT;
using poly::mod;
using poly::ksm;
const int maxn=1e7+7;
int jc[maxn];
int inv[maxn];
inline void pre(){
jc[0]=inv[0]=1;
for(register int t=1;t<maxn;++t)
jc[t]=1ll*jc[t-1]*t%mod;
inv[maxn-1]=ksm(jc[maxn-1],mod-2);
for(register int t=maxn-2;t;--t)
inv[t]=1ll*inv[t+1]*(t+1)%mod;
for(register int t=0;t<maxn;++t)
if(1ll*inv[t]*jc[t]%mod!=1) puts("WA");
}
inline int c(const int&n,const int&m){
if(n<m)return 0;
return 1ll*jc[n]*inv[m]%mod*inv[n-m]%mod;
}
int n,m,s,L;
int f[maxn];
int g[maxn];
int main(){
#ifndef ONLINE_JUDGE
freopen("in.in","r",stdin);
#endif
pre();
n=qr();m=qr();s=qr();
L=min(n/s,min(m,n));
for(register int t=0;t<=L;++t){
f[t]=1ll*c(m,t)*jc[n]%mod*ksm(m-t,n-s*t)%mod*inv[n-s*t]%mod*ksm(ksm(jc[s],t),mod-2)%mod*jc[t]%mod;
}
for(register int t=0;t<=L;++t){
g[t]=inv[L-t];
if((L-t)&1)g[t]=mod-g[t];
}
int k=1;
while(k<=L)k<<=1;
NTT(f,k<<1,1);
NTT(g,k<<1,1);
for(register int t=0;t<k<<1;++t) g[t]=1ll*g[t]*f[t]%mod;
NTT(g,k<<1,-1);
int ans=0;
for(register int t=0;t<=L;++t) ans=(ans+1ll*qr()*g[t+L]%mod*inv[t]%mod)%mod;
printf("%d\n",ans);
return 0;
}
【题解】[HAOI2018]染色(NTT+容斥/二项式反演)的更多相关文章
- [HAOI2018]染色(容斥+NTT)
补充一篇详细得不能再详细的题解,比如让我自己看懂. 可能与前面的题解有些相同,我想补充一下自己的想法. 显然,最多 \(K\) 最大为 \(N=min(\lfloor \frac nS\rfloor, ...
- P4491 [HAOI2018]染色 广义容斥 NTT 生成函数
LINK:染色 算是比较常规的广义容斥. 算恰好k个 可以直接转成至少k个. 至少k个非常的好求 直接生成函数. 设\(g_k\)表示至少有k个颜色是满足的 那么有 \(g_k=C(m,k)\frac ...
- 51nod 1518 稳定多米诺覆盖(容斥+二项式反演+状压dp)
[传送门[(http://www.51nod.com/Challenge/Problem.html#!#problemId=1518) 解题思路 直接算不好算,考虑容斥,但并不能把行和列一起加进去容斥 ...
- NOI Online 游戏 树形dp 广义容斥/二项式反演
LINK:游戏 还是过于弱鸡 没看出来是个二项式反演,虽然学过一遍 但印象不深刻. 二项式反演:有两种形式 一种是以恰好和至多的转换 一种是恰好和至少得转换. 设\(f_i\)表示至多的方案数 \(g ...
- HDU 2841 容斥 或 反演
$n,m <= 1e5$ ,$i<=n$,$j<=m$,求$(i⊥j)$对数 /** @Date : 2017-09-26 23:01:05 * @FileName: HDU 284 ...
- 【题解】Counting D-sets(容斥+欧拉定理)
[题解]Counting D-sets(容斥+欧拉定理) 没时间写先咕咕咕. vjCodeChef - CNTDSETS 就是容斥,只是难了一二三四五\(\dots \inf\)点 题目大意: 给定你 ...
- [模板] 容斥原理: 二项式反演 / Stirling 反演 / min-max 容斥 / 子集反演 / 莫比乌斯反演
//待更qwq 反演原理 二项式反演 若 \[g_i=\sum_{j=1}^i {\binom ij} f_j\] , 则有 \[ f_i=\sum_{j=1}^i (-1)^{i-j} {i \ch ...
- HAOI 2018 染色(容斥+NTT)
题意 https://loj.ac/problem/2527 思路 设 \(f(k)\) 为强制选择 \(k\) 个颜色出现 \(s\) 种,其余任取的方案数. 则有 \[ f(k)={m\choos ...
- [acmm week12]染色(容斥定理+组合数+逆元)
1003 染色 Time Limit: 1sec Memory Limit:256MB Description 今天离散数学课学了有关树的知识,god_v是个喜欢画画的人,所以他 ...
随机推荐
- 【Flask源码分析——请求上下文与应用上下文】
Flask中有两种上下文,请求上下文和应用上下文.两者的作用域都处于一个请求的局部中. 查看源代码,上下文类在flask.ctx模块中定义 AppContext类定义应用上下文,app是当前应用Web ...
- oracle函数 TRIM(c1 from c2)
[功能]删除左边和右边出现的字符串 [参数]C2 删除前字符串 c1 删除字符串,默认为空格 [返回]字符型 [示例] select TRIM('X' from 'XXXgao qian jingXX ...
- HZOJ big
考试的时候理解错题了(无语)…… 那个看似很长的式子的意义其实是逻辑左移动,就是最高位会出现在最低位的意思(这谁能看出来……).此时x取值经过那个式子后仍然可以遍历[0,2^n), O(m)枚举断点, ...
- IDEA 通过数据库生成entity实体类
IDEA利用数据库生成entity类教程 1.在左上角有一个View 选项 2. 然后选择 TOOL Windows 3. 然后选择Database然后会弹出一个窗口 4.选择+号 5.选择data ...
- 开源中国 2014 最受关注开源软件排行榜 TOP 50
开源中国 2014 最受关注开源软件排行榜 TOP 50 开源中国 2014 年最受关注软件排行榜 TOP 50 正式出炉!2014 年结束了,我们来了解一下过去一年里开源中国最受欢迎的 50 款软件 ...
- react框架下,在页面内加载显示PDF文件,关于react-pdf-js的使用注意事项
react框架下,在页面内加载显示PDF文件,关于react-pdf-js的使用注意事项 之前做了一个需求,在注册账号的时候,让用户同意服务条款, 服务条款是一个PDF文件, 这就需要在react内加 ...
- poj 1263 Reflections (Simple Geometry)
1263 -- Reflections 简单计算几何.题目给出射线以及若干个不相交的圆,求出射线会在哪些圆上反弹,依次写出反弹球的编号. 代码如下: #include <cstdio> # ...
- SuperSocket性能数据采集的应用程序接口的改动
性能数据采集的应用程序接口作了修改,两个虚方法已经被更改: protected virtual void UpdateServerSummary(ServerSummary serverSummary ...
- H3C 数据封装与解封装
- 【原生JS】自动渐变轮播
渐变主要是通过CSS3的动画实现. 只需给css中添加transtion动画时间加上JS设置指定图片透明度显示与消失即可实现渐变过程. 效果图: HTML: <!DOCTYPE html> ...