Solution -「CTS2019」珍珠
题目
题解
先 % 兔。同为兔子为什么小粉兔辣么强qwq。 本文大体跟随小粉兔的题解的思路,并为像我一样多项式超 poor 的读者作了很详细的解释。如果题解界面公式出现问题,可以尝试“在 Ta 的博客查看”w~
生成函数 + NTT。
首先,转化题意:求长度为 \(n\),元素属于 \([1,D]\) 且存在至少 \(m\) 对位置不重复的相同元素的整数序列个数。
不妨把元素的值形象化为颜色,设第 \(c\) 中颜色在某个序列中出现次数为 \(cnt_c\)。则该序列合法,当且仅当:
\]
也即是,每种颜色最多组合出 \(\lfloor\frac{cnt_c}2\rfloor\) 组相同元素对,并将其求和。对 \((1)\) 变形:
\]
\]
\]
\]
由 \((2)\),产生了一些特判:当 \(n<2m\),非负数之和不可能小于 \(0\),答案为 \(0\);当 \(D\le n-2m\),等式恒成立(颜色总数仅 \(D\)),答案为 \(D^n\)。
接下来,令 \(g_i\) 表示恰好有 \(i\) 个 \(cnt_c\bmod2=1\) 的方案数。即 \(g_i=\sum_{cnt}[\sum_{c=1}^Dcnt_c\bmod2=i]\)。可以发现最终答案为 \(\sum_{c=0}^{n-2m}g_c\),即 \((2)\) 的等式左边所有满足条件的取值的方案数之和。
然后容斥 \(g\):令 \(f_i\) 为至少有 \(i\) 个 \(cnt_c\bmod2=1\) 的方案数。注意:\(f\) 考虑了与 \(g\) 的容斥关系。更细致地阐释,\(f_i\) 表示先保证有 \(i\) 个颜色为奇数的前提下,其它颜色任意选的方案总数。如此一来,对于任意 \(i\ge j\), \(g_i\) 会对 \(f_j\) 贡献 \(i\choose j\) 次——在 \(i\) 中选 \(j\) 个“保底”,其余 \(i-j\) 个成为“任意选”方案中的若干种。则:
\]
利用二项式反演,对 \((3)\) 变形:
\]
可以发现,在最后一个式子的求和中,点乘号左右两边分别是关于 \(j\) 和 \(i-j\) 的函数,那么 \(g\) 实际上就是一个卷积的形式。只要求出 \(f\) 即可。
回顾 \(f\) 的定义,并尝试引入指数型生成函数。考虑到对于序列 \(C=\{1,1,1,\dots\}\),其生成函数为 \(G_e(C)=\sum_i\frac{x^i}{i!}=e^x\);对于序列 \(O=\{0,1,0,1,\dots\}\),其生成函数为 \(G_e(O)=\frac{x_1}{1!}+\frac{x_3}{3!}+\frac{x_5}{5!}+\cdots=\frac{e^x-e^{-x}}2\)。同时,记 \([x^n]f(x)\) 表示函数 \(f(x)\) 的 \(n\) 次项系数,则有:
\]
先停下来理解:
第一项 \(D\choose i\),先钦定 \(D\) 种颜色中的 \(i\) 个为必须奇数。别忘了 \(f\) 定义,其余颜色也可以为奇数,它们是任意的。
第二项 \(n!\),是约掉指数生成函数第 \(n\) 项的 \(\frac{1}{n!}\)。比如 \([x^3]G_e(C)=\frac{1}{3!}\),需要乘上 \(\frac{1}{3!}\) 才为 \(1\)。
第三项 \([x^n]\left(G_e^i(O)G_e^{D-i}(C)\right)\),正如一般的卷积,生成函数的卷积表现了在不同集合中选择的方案。该式中卷积的第 \(n\) 项就表示选择 \(i\) 个奇数,再任选 \(D-i\) 个非负数,使得其和恰为 \(n\) 的方案数。可以结合最初的题意理解。
理解之后,着手对 \((5)\) 变形(注意所有的 \(i\) 均为下标,而非虚数单位):
\]
\]
利用二项式定理,展开 \((6)\) 中的 \((e^x-e^{-x})^i\),得:
\]
\]
发现 \(e^{(D+2j-2i)x}\) 是形如 \(e^{ax}\) 的形式,而 \(e^{ax}\) 是序列 \(\{a^0,a^1,a^2,\dots\}\) 的生成函数。所以其 \(n\) 次项应为 \(\frac{a^n}{n!}\)。则 \([x^n]e^{(D+2j-2i)x}=\frac{(D+2j-2i)^n}{n!}\)。将其代入 \((7)\) 并整理:
\]
\]
\]
把 \((8)\) 朝着卷积的形式靠近,即分开 \(i-j\) 与 \(j\)。为了美观,令 \(k=i-j\),则 \(j=i-k\)。推出:
\]
此时,和式已经是卷积的形式。
到此,利用 NTT,通过 \((9)\) 求出 \(f\),再通过 \((4)\) 求出 \(g\),最后求得答案为 \(\sum_{c=0}^{n-2m}g_c\),并记得特判 \((2)\) 所引出的两种情况,这道题就解决啦~
代码
#include <cstdio>
const int MOD = 998244353, G = 3, INV2 = ( MOD + 1 ) >> 1, MAXD = 1 << 18;
int D, n, m, inv[MAXD + 5], fac[MAXD + 5], ifac[MAXD + 5];
int A[MAXD + 5], B[MAXD + 5], rev[MAXD + 5];
inline int qkpow ( int a, int b, const int p = MOD ) {
int ret = 1;
for ( ; b; a = 1ll * a * a % p, b >>= 1 ) ret = 1ll * ret * ( b & 1 ? a : 1 ) % p;
return ret;
}
inline void NTT ( const int n, int* a, const int tp ) {
for ( int i = 0; i < n; ++ i ) {
if ( i < rev[i] ) {
a[i] ^= a[rev[i]] ^= a[i] ^= a[rev[i]];
}
}
for ( int i = 2, stp = 1; i <= n; i <<= 1, stp <<= 1 ) {
int w = qkpow ( G, ( MOD - 1 ) / i );
if ( ! ~ tp ) w = qkpow ( w, MOD - 2 );
for ( int j = 0; j < n; j += i ) {
for ( int k = j, r = 1; k < j + stp; ++ k, r = 1ll * r * w % MOD ) {
int ev = a[k], ov = 1ll * a[k + stp] * r % MOD;
a[k] = ( ev + ov ) % MOD, a[k + stp] = ( ev - ov + MOD ) % MOD;
}
}
}
if ( ! ~ tp ) {
int rvn = qkpow ( n, MOD - 2 );
for ( int i = 0; i < n; ++ i ) a[i] = 1ll * a[i] * rvn % MOD;
}
}
inline void polyConv ( int lenA, int lenB, int* A, int* B, int* C ) {
int lenC = lenA + lenB - 1, len = 1, lg = 0;
for ( ; len < lenC; len <<= 1, ++ lg );
for ( int i = 0; i < len; ++ i ) rev[i] = ( rev[i >> 1] >> 1 ) | ( ( i & 1 ) << lg >> 1 );
static int tmpA[MAXD + 5], tmpB[MAXD + 5];
for ( int i = 0; i < len; ++ i ) {
tmpA[i] = i < lenA ? A[i] : 0;
tmpB[i] = i < lenB ? B[i] : 0;
}
NTT ( len, tmpA, 1 ), NTT ( len, tmpB, 1 );
for ( int i = 0; i < len; ++ i ) C[i] = 1ll * tmpA[i] * tmpB[i] % MOD;
NTT ( len, C, -1 );
}
inline void init () {
inv[1] = fac[1] = ifac[1] = fac[0] = ifac[0] = 1;
for ( int i = 2; i <= D; ++ i ) {
fac[i] = 1ll * i * fac[i - 1] % MOD;
inv[i] = 1ll * ( MOD - MOD / i ) * inv[MOD % i] % MOD;
ifac[i] = 1ll * inv[i] * ifac[i - 1] % MOD;
}
}
int main () {
scanf ( "%d %d %d", &D, &n, &m );
if ( m << 1 > n ) return puts ( "0" ), 0;
if ( m << 1 <= n - D ) return printf ( "%d\n", qkpow ( D, n ) ), 0;
init ();
for ( int i = 0; i <= D; ++ i ) {
A[i] = 1ll * qkpow ( ( D - 2 * i + MOD ) % MOD, n ) * ( i & 1 ? MOD - ifac[i] : ifac[i] ) % MOD;
B[i] = ifac[i];
}
polyConv ( D + 1, D + 1, A, B, A );
for ( int i = 0; i <= D; ++ i ) {
A[i] = 1ll * A[i] * fac[D] % MOD * fac[i] % MOD * qkpow ( INV2, i ) % MOD * ifac[D - i] % MOD;
B[D - i] = i & 1 ? MOD - ifac[i] : ifac[i];
}
polyConv ( D + 1, D + 1, A, B, A );
int ans = 0;
for ( int i = 0; i <= n - 2 * m; ++ i ) ans = ( ans + 1ll * ifac[i] * A[D + i] ) % MOD;
printf ( "%d\n", ans );
return 0;
}
Solution -「CTS2019」珍珠的更多相关文章
- 「CTS2019」珍珠
「CTS2019」珍珠 解题思路 看了好多博客才会,问题即要求有多少种方案满足数量为奇数的变量数 \(\leq n-2m\).考虑容斥,令 \(F(k)\) 为恰好有 \(n\) 个变量数量为奇数的方 ...
- LOJ3120. 「CTS2019」珍珠 [容斥,生成函数]
传送门 思路 非常显然,就是要统计有多少种方式使得奇数的个数不超过\(n-2m\).(考场上这个都没想到真是身败名裂了--) 考虑直接减去钦点\(n-2m+1\)个奇数之后的方案数,但显然这样会算重, ...
- 「CTS2019」氪金手游
「CTS2019」氪金手游 解题思路 考场上想出了外向树的做法,居然没意识到反向边可以容斥,其实外向树会做的话这个题差不多就做完了. 令 \(dp[u][i]\) 表示单独考虑 \(u\) 节点所在子 ...
- Solution -「构造」专练
记录全思路过程和正解分析.全思路过程很 navie,不过很下饭不是嘛.会持续更新的(应该). 「CF1521E」Nastia and a Beautiful Matrix Thought. 要把所有数 ...
- Solution -「原创」Destiny
题目背景 题目背景与题目描述无关.签到愉快. 「冷」 他半靠在床沿,一缕感伤在透亮的眼眸间荡漾. 冷见惆怅而四散逃去.经历嘈杂喧嚣,感官早已麻木.冷又见空洞而乘隙而入.从里向外,这不是感官的范畴. 他 ...
- Solution -「GLR-R2」教材运送
\(\mathcal{Description}\) Link. 给定一棵包含 \(n\) 个点,有点权和边权的树.设当前位置 \(s\)(初始时 \(s=1\)),每次在 \(n\) 个结点内 ...
- Solution -「WF2011」「BZOJ #3963」MachineWorks
\(\mathcal{Description}\) Link. 给定你初始拥有的钱数 \(C\) 以及 \(N\) 台机器的属性,第 \(i\) 台有属性 \((d_i,p_i,r_i,g_i ...
- Solution -「LOCAL」二进制的世界
\(\mathcal{Description}\) OurOJ. 给定序列 \(\{a_n\}\) 和一个二元运算 \(\operatorname{op}\in\{\operatorname{ ...
- Solution -「SHOI2016」「洛谷 P4336」黑暗前的幻想乡
\(\mathcal{Description}\) link. 有一个 \(n\) 个结点的无向图,给定 \(n-1\) 组边集,求从每组边集选出恰一条边最终构成树的方案树.对 \(10^9+ ...
随机推荐
- PowerShell 之常用方法
随笔分类 - 常用 [PowerShell]文件的解压与压缩 摘要:1 New-Item -ItemType File 1.txt -Force #新建文本文件 2 Compress-Archive ...
- FastDFS的应用
一.定义 FastDFS是由淘宝的余庆先生所开发的一个轻量级.高性能的开源分布式文件系统.用纯C语言开发,功能丰富: 文件存储 文件同步 文件访问(上传.下载) 存取负载均衡 在线扩容 适合有大容量存 ...
- 链式printf()函数的用法
printf()函数:十进制格式型输出函数. #include <stdio.h> int printf( const char *format, ... ); 1.首先printf的返回 ...
- mysql数据库优化1
目录 数据库结构的设计优化 1.数据库结构的设计 2.针对大型的数据量提前进行分库和分表 3.分库分表带来的问题 4.表结构设计注意的问题 查询优化 1.查询语句的注意事项 2.应尽量避免在 wher ...
- rocketmq实现延迟队列精确到秒级实现方案2-时间轮和delay-file实现
上图是通过RocketMQ源码分析一个实现原理方案示意图. 分为两个部分: 消息的写入消息的Schedule 在写入CommitLog之前,如果是延迟消息,按照每10分钟写入delayfile文件,对 ...
- C++中的const和mutable
1 #include<iostream> 2 using namespace std; 3 //如果在类A的成员函数dis()中想要修改_z,但是不能修改_x,_y怎么办? 4 //如果d ...
- Tomcat访问项目出现HTTP状态404-未找到,类型 状态报告 描述 源服务器未能找到目标资源的表示或者是不愿公开一个已经存在的资源表示。Apache Tomcat/9.0.40
错误提示如图,无任何消息提示,控制台也没有错误. 解决方法: IDEA,上方菜单栏点击Run–>Edit Configurations-,选择Deployment,将Application co ...
- Nginx配置文件nginx.conf有哪些属性模块?
worker_processes 1: # worker进程的数量 events { # 事件区块开始 worker_connections 1024: # 每个worker进程支持的最大连接数 } ...
- Java安全之C3P0利用与分析
Java安全之C3P0利用与分析 目录 Java安全之C3P0利用与分析 写在前面 C3P0 Gadget http base C3P0.getObject() 序列化 反序列化 Class.forN ...
- Java 中对象锁和类锁的区别? 关键字 Synchronized的用法?
一 对象锁和类锁的关系 /* * 对象锁和[类锁] 全局锁的关系? 对象锁是用于对象实例方法,或者一个对象实例上的 this 类锁是用于类的静态方法或者一个类的class对象上的. Ag.class ...