显然相当于求有不超过n-2m种颜色出现奇数次的方案数。由于相当于是对各种颜色选定出现次数后有序排列,可以考虑EGF。

  容易构造出EGF(ex-e-x)/2=Σx2k+1/(2k+1)!,即表示该颜色只能选奇数个。同理有EGF(ex+e-x)/2=Σx2k/(2k)!,即表示该颜色只能选偶数个。

  考虑暴力枚举有多少种颜色出现了奇数次。不妨设恰有i种颜色出现了奇数次的方案数为f(i),那么f(i)=n!·C(D,i)·[xn](((ex-e-x)/2)i·((ex+e-x)/2)D-i),答案显然为Σf(i) (i=0~n-2m)。

  然而看了一眼题解这种求f(i)的方式可能有点麻烦,不妨考虑容斥,设g(i)为钦定有i种颜色出现了奇数次的方案数,则显然有f(i)=Σ(-1)j-i·C(j,i)·g(j)。如果求得了所有g(i),f(i)显然可以NTT计算。

  于是考虑求g(i),有g(i)=n!·C(D,i)·[xn](((ex-e-x)/2)i·(ex)D-i),后一个EGF变的更简单,更易推导。使用二项式定理暴力展开前一个EGF,有g(i)=n!·C(D,i)·[xn](ΣC(i,j)·(-1)j·e-jx·e(i-j)x)·e(D-i)x/2i,指数相加后变成异常优美的g(i)=n!·C(D,i)·[xn](ΣC(i,j)·(-1)j·e(D-2j)x)/2i。由泰勒展开容易知道[xn]e(D-2j)x=(D-2j)n/n!。于是g(i)=C(D,i)/2i·ΣC(i,j)·(-1)j·(D-2j)n。同样是卷积形式,NTT计算即可。

  虽然推导过程看起来很简单,但这辈子都不可能会的。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define P 998244353
#define N 550000
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int D,n,m,f[N],g[N],r[N],fac[N],inv[N],ans;
int ksm(int a,int k)
{
if (a<0) a+=P;
int s=1;
for (;k;k>>=1,a=1ll*a*a%P) if (k&1) s=1ll*s*a%P;
return s;
}
int Inv(int a){return ksm(a,P-2);}
void DFT(int *a,int n,int g)
{
for (int i=0;i<n;i++) if (i<r[i]) swap(a[i],a[r[i]]);
for (int i=2;i<=n;i<<=1)
{
int wn=ksm(g,(P-1)/i);
for (int j=0;j<n;j+=i)
{
int w=1;
for (int k=j;k<j+(i>>1);k++,w=1ll*w*wn%P)
{
int x=a[k],y=1ll*w*a[k+(i>>1)]%P;
a[k]=(x+y)%P,a[k+(i>>1)]=(x-y+P)%P;
}
}
}
}
void FFT(int *f,int *g,int t)
{
DFT(f,t,3),DFT(g,t,3);
for (int i=0;i<t;i++) f[i]=1ll*f[i]*g[i]%P;
DFT(f,t,Inv(3));
for (int i=0;i<t;i++) f[i]=1ll*f[i]*Inv(t)%P;
}
int C(int n,int m){return 1ll*fac[n]*inv[m]%P*inv[n-m]%P;}
int main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
D=read(),n=read(),m=read();
m=n-2*m;
if (m>=D) {cout<<ksm(D,n);return 0;}
if (m<0) {cout<<0;return 0;}
fac[0]=1;for (int i=1;i<=D;i++) fac[i]=1ll*fac[i-1]*i%P;
inv[0]=inv[1]=1;for (int i=2;i<=D;i++) inv[i]=P-1ll*(P/i)*inv[P%i]%P;
for (int i=2;i<=D;i++) inv[i]=1ll*inv[i-1]*inv[i]%P;
int t=1;while (t<=(D<<1)) t<<=1;
for (int i=0;i<t;i++) r[i]=(r[i>>1]>>1)|(i&1)*(t>>1);
for (int i=0;i<=D;i++) f[i]=1ll*ksm(-1,i)*ksm(D-2*i,n)%P*inv[i]%P;
for (int i=0;i<=D;i++) g[i]=inv[i];
FFT(f,g,t);
for (int i=0;i<=D;i++) f[i]=1ll*f[i]*fac[i]%P*ksm(Inv(2),i)%P*C(D,i)%P;
for (int i=0;i<=D;i++) f[i]=1ll*f[i]*fac[i]%P;
for (int i=D+1;i<t;i++) f[i]=0;
for (int i=0;i<=D;i++) g[i]=1ll*ksm(-1,i)*inv[i]%P;
reverse(g,g+D+1);
for (int i=D+1;i<t;i++) g[i]=0;
FFT(f,g,t);
for (int i=D;i<=D+D;i++) f[i]=1ll*f[i]*inv[i-D]%P;
for (int i=D;i<=D+m;i++) ans=(ans+f[i])%P;
cout<<ans;
return 0;
}

  

Luogu5401 CTS2019珍珠(生成函数+容斥原理+NTT)的更多相关文章

  1. LOJ3120 CTS2019 珍珠 生成函数、二项式反演、NTT

    传送门 题目大意:给出一个长度为\(n\)的序列\(a_i\),序列中每一个数可以取\(1\)到\(D\)中的所有数.问共有多少个序列满足:设\(p_i\)表示第\(i\)个数在序列中出现的次数,\( ...

  2. [LOJ#3120][Luogu5401][CTS2019]珍珠(容斥+生成函数)

    https://www.luogu.org/blog/user50971/solution-p5401 #include<cstdio> #include<algorithm> ...

  3. 题解-CTS2019 珍珠

    题面 CTS2019 珍珠 有 \(n\) 个在 \([1,d]\) 内的整数,求使可以拿出 \(2m\) 个整数凑成 \(m\) 个相等的整数对的方案数. 数据范围:\(0\le m\le 10^9 ...

  4. [CTS2019]珍珠——二项式反演

    [CTS2019]珍珠 考虑实际上,统计多少种染色方案,使得出现次数为奇数的颜色数<=n-2*m 其实看起来很像生成函数了 n很大?感觉生成函数会比较整齐,考虑生成函数能否把n放到数值的位置,而 ...

  5. 【题解】CTS2019珍珠(二项式反演+卷积)

    [题解]CTS2019珍珠 题目就是要满足这样一个条件\(c_i\)代表出现次数 \[ \sum {[\dfrac {c_i } 2]} \ge 2m \] 显然\(\sum c_i=n\)所以,而且 ...

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

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

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

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

  8. [CTS2019]珍珠(NTT+生成函数+组合计数+容斥)

    这题72分做法挺显然的(也是我VP的分): 对于n,D<=5000的数据,可以记录f[i][j]表示到第i次随机有j个数字未匹配的方案,直接O(nD)的DP转移即可. 对于D<=300的数 ...

  9. BZOJ1042 HAOI2008硬币购物(任意模数NTT+多项式求逆+生成函数/容斥原理+动态规划)

    第一眼生成函数.四个等比数列形式的多项式相乘,可以化成四个分式.其中分母部分是固定的,可以多项式求逆预处理出来.而分子部分由于项数很少,询问时2^4算一下贡献就好了.这个思路比较直观.只是常数巨大,以 ...

随机推荐

  1. TLS整理(下):TLS如何保证安全

    明文 无法验证服务器的真实性 从而引出了TLS.本篇就来着重介绍下TLS. 说起TLS可能有些人还比较陌生,但如果说到SSL,那知道的人就更多了.TLS其实就是SSL发展而来,版本演进大体为SSL 2 ...

  2. 在Eclipse IDE进行Struts开发时提示错误:java.lang.ClassNotFoundException: org.apache.struts2.dispatcher.FilterDispatcher的解决办法

    If you have... included all necessary jars Configured build path correctly added them all in deploym ...

  3. 小D课堂 - 零基础入门SpringBoot2.X到实战_第9节 SpringBoot2.x整合Redis实战_39、SpringBoot2.x整合redis实战讲解

    笔记 3.SpringBoot2.x整合redis实战讲解 简介:使用springboot-starter整合reids实战 1.官网:https://docs.spring.io/spring-bo ...

  4. socket status 的状态变化详解

    原文链接: http://www.diranieh.com/SOCKETS/SocketStates.htm --------------------------------------------- ...

  5. lintcode 394. Coins in a Line 、leetcode 292. Nim Game 、lintcode 395. Coins in a Line II

    变型:如果是最后拿走所有石子那个人输,则f[0] = true 394. Coins in a Line dp[n]表示n个石子,先手的人,是必胜还是必输.拿1个石子,2个石子之后都是必胜,则当前必败 ...

  6. Fiddler抓包工具版面认识(一)

    Fiddler是一个蛮好用的抓包工具,可以将网络传输发送与接受的数据包进行截获.重发.编辑.转存等操作.也可以用来检测网络安全.反正好处多多,举之不尽呀!当年学习的时候也蛮费劲,一些蛮实用隐藏的小功能 ...

  7. maven项目新检出后不编译爬坑记 及 mvn clean package报错 WagonTransporterFactory: java.util.NoSuchElementException 异常【我】

    从SVN新检出一个maven项目,配置好后,发现项目无法编译(只有一个test包中的代码显示编译报错,其他所有包中的代码都不编译,也不报错), 先注释掉报错的test包中的所有内容, 用Eclipse ...

  8. 深入学习c++--智能指针(二) weak_ptr(打破shared_ptr循环引用)

    1. 几种智能指针 1. auto_ptr: c++11中推荐不使用他(放弃) 2. shared_ptr: 拥有共享对象所有权语义的智能指针 3. unique_ptr: 拥有独有对象所有权语义的智 ...

  9. 转 mysql awr 报告

    1. https://github.com/noodba/myawr 2. https://www.cnblogs.com/zhjh256/p/5779533.html

  10. Python - Django - ORM 一对一表结构

    当一张表的某一些字段查询的比较频繁,另外一些字段查询的不是特别频繁,可以把不怎么常用的字段 单独拿出来做成一张表,然后用一对一的表关联起来 这样既保证数据都完整的保存下来,又能保证检索更快 model ...