\[\begin{aligned}
Ans(k) &= \sum \limits_{i = 1}^n \sum \limits_{j = 1}^m \sum \limits_{t = 0}^k \binom{k}{t} a_i^t b_j^{k - t} \\
&= \sum \limits_{t = 0}^k \binom{k}{t} (\sum \limits_{i = 1}^n a_i^t) (\sum \limits_{j = 1}^m b_i^{k - t}) \\
&= k! * \sum \limits_{t = 0}^k (\frac{\sum \limits_{i = 1}^n a_i^t}{t!}) (\frac{\sum \limits_{j = 1}^m b_i^{k - t}}{(k - t)!}) \\
\end{aligned}
\]

右边是一个卷积,只需考虑对\(t = 0, 1 ..., n\)求出\(f(t) = \sum \limits_{i = 1}^n a_i^t\)


考虑生成函数\(OGF\)

\[\begin{aligned}
F(x) &= \sum \limits_{i = 0}^{\infty} f(i) * x^i \\
&= \sum \limits_{i = 1}^{\infty} \sum \limits_{j = 1}^{n} a_j^i \\
&= \sum \limits_{i = 1}^n (\sum \limits_{j = 0}^{\infty} (a_ix)^j) \\
&= \sum \limits_{i = 1}^n \frac{1}{1 - a_i x}
\end{aligned}
\]

那么,现在的问题在于如何求解

\[\sum \limits_{i = 1}^n \frac{1}{1 - a_i x}
\]


考虑分治\(FFT\)

一种很好想的思路是先求出\(\sum \limits_{i = 1}^l \frac{1}{1 - a_i x}\)和\(\sum \limits_{i = l + 1}^r \frac{1}{1 - a_i x}\)

它们一定是形如\(\frac{A}{B}\)的一个式子,不妨设左边为\(\frac{A}{B}\),右边为\(\frac{C}{D}\)

那么合并之后的形式为\(\frac{AD + BC}{BD}\),然后维护即可

复杂度\(O(n log^2 n)\)


可以发现$$In'(a * b) = (In(a) + In(b))' = In'(a) + In'(b)$$

因此,我们考虑$$In'(\frac{1}{1 - a_i x}) = \frac{-a_i}{1 - a_i x}$$

注意不能在\(In\)中添加常数因子,因此我们只能从这个形式来考虑

\[\begin{aligned}
G(x) &= \sum \limits_{i = 1}^n In'(\frac{1}{1 - a_i x}) \\
&= In ' (\prod \limits_{i = 1}^n \frac{1}{1 - a_i x})
\end{aligned}
\]

可以用分治\(FFT\)求出\(G\)

观察数列

\[F(x) = a_i^0 + a_i^1 x^1 + a_i^2 x^2 + a_i^3 x^3 ...
\]

\[G(x) = -a_i^1 - a_i^2 x^1 - a_i^3 x^2 + ...
\]

因此,$$-xG(x) + n = F(x)$$

然后就可以啦


#include <bits/stdc++.h>
using namespace std; #define ri register int
#define rep(io, st, ed) for(ri io = st; io <= ed; io ++)
#define drep(io, ed, st) for(ri io = ed; io >= st; io --) const int sid = 5e5 + 5;
const int mod = 998244353; #define gc getchar
inline int read() {
int p = 0, w = 1; char c = gc();
while(c > '9' || c < '0') { if(c == '-') w = -1; c = gc(); }
while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc();
return p * w;
} inline int Inc(int a, int b) { return (a + b >= mod) ? a + b - mod : a + b; }
inline int Dec(int a, int b) { return (a - b < 0) ? a - b + mod : a - b; }
inline int mul(int a, int b) { return 1ll * a * b % mod; }
inline int fp(int a, int k) {
int ret = 1;
for( ; k; k >>= 1, a = mul(a, a))
if(k & 1) ret = mul(ret, a);
return ret;
} int rev[sid], fac[sid], inv[sid], ivf[sid];
int a[sid], b[sid], ak[sid], bk[sid]; inline void init(int Mn, int &n, int &lg) {
n = 1; lg = 0;
while(n < Mn) n <<= 1, lg ++;
} inline void NTT(int *a, int n, int opt) {
for(ri i = 0; i < n; i ++)
if(i < rev[i]) swap(a[i], a[rev[i]]);
for(ri i = 1; i < n; i <<= 1)
for(ri j = 0, g = fp(3, (mod - 1) / (i << 1)); j < n; j += (i << 1))
for(ri k = j, G = 1; k < i + j; k ++, G = mul(G, g)) {
int x = a[k], y = mul(G, a[i + k]);
a[k] = (x + y >= mod) ? x + y - mod : x + y;
a[i + k] = (x - y < 0) ? x - y + mod : x - y;
}
if(opt == -1) {
reverse(a + 1, a + n);
int ivn = fp(n, mod - 2);
for(ri i = 0; i < n; i ++) a[i] = mul(a[i], ivn);
}
} int ia[sid], ib[sid];
inline void Inv(int *a, int *b, int n) {
if(n == 1) { b[0] = fp(a[0], mod - 2); return; }
Inv(a, b, n >> 1); int N = 1, lg = 0; init(n + n, N, lg);
for(ri i = 0; i < N; i ++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (lg - 1));
for(ri i = 0; i < N; i ++) ia[i] = ib[i] = 0;
for(ri i = 0; i < n; i ++) ia[i] = a[i], ib[i] = b[i]; NTT(ia, N, 1); NTT(ib, N, 1);
for(ri i = 0; i < N; i ++) ia[i] = Dec((ib[i] << 1) % mod, mul(ia[i], mul(ib[i], ib[i])));
NTT(ia, N, -1); for(ri i = 0; i < n; i ++) b[i] = ia[i];
} inline void Init_Inv(int n) {
inv[0] = inv[1] = 1;
for(int i = 2; i <= n; i ++) inv[i] = mul(inv[mod % i], mod - mod / i);
fac[0] = fac[1] = 1;
for(int i = 2; i <= n; i ++) fac[i] = mul(fac[i - 1], i);
ivf[0] = ivf[1] = 1;
for(int i = 2; i <= n; i ++) ivf[i] = mul(ivf[i - 1], inv[i]);
} inline void wf(int *a, int *b, int n) { for(ri i = 1; i < n; i ++) b[i - 1] = mul(a[i], i); }
inline void jf(int *a, int *b, int n) { for(ri i = 1; i < n; i ++) b[i] = mul(a[i - 1], inv[i]);} int da[sid], iva[sid];
inline void In(int *a, int *b, int n) {
for(ri i = 0; i < n + n; i ++) da[i] = iva[i] = 0;
Inv(a, iva, n); wf(a, da, n); int N = 1, lg = 0; init(n + n, N, lg);
for(ri i = 0; i < N; i ++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (lg - 1)); NTT(da, N, 1); NTT(iva, N, 1);
for(ri i = 0; i < N; i ++) da[i] = mul(da[i], iva[i]);
NTT(da, N, -1); jf(da, b, n);
} int hb[sid], inb[sid];
inline void Exp(int *a, int *b, int n) {
if(n == 1) { b[0] = 1; return; }
Exp(a, b, n >> 1); int N = 1, lg = 0; init(n + n, N, lg);
for(ri i = 0; i < N; i ++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (lg - 1)); for(ri i = 0; i < N; i ++) inb[i] = hb[i] = 0;
In(b, inb, n);
for(ri i = 0; i < n; i ++) hb[i] = Dec(a[i], inb[i]); hb[0] ++; NTT(inb, N, 1); NTT(hb, N, 1);
for(ri i = 0; i < N; i ++) inb[i] = mul(inb[i], hb[i]);
NTT(inb, N, -1); for(ri i = 0; i < n; i ++) b[i] = inb[i];
} int Ib[sid], F[sid * 2], pa[sid], pb[sid];
inline void calc(int *a, int *b, int n, int t) {
int N = 1, lg = 0;
init(max(n, t) + 5, N, lg);
for(ri i = 0; i < (N << 1); i ++) F[i] = 0;
for(ri i = 0; i < n; i ++) F[2 * i] = 1, F[2 * i + 1] = mod - a[i + 1];
for(ri i = n; i < N; i ++) F[2 * i] = 1;
for(ri i = 1; i < N; i <<= 1) {
for(ri j = 0; j < N; j += (i << 1)) {
int M = 1, lg = 0;
init((i << 2), M, lg);
for(ri k = 0; k < M; k ++) rev[k] = (rev[k >> 1] >> 1) | ((k & 1) << (lg - 1));
for(ri k = 0; k < M; k ++) pa[k] = pb[k] = 0;
for(ri k = 0; k < (i << 1); k ++)
pa[k] = F[(j << 1) + k], pb[k] = F[(j << 1) + (i << 1) + k];
NTT(pa, M, 1); NTT(pb, M, 1);
for(ri k = 0; k < M; k ++) pa[k] = mul(pa[k], pb[k]);
NTT(pa, M, -1);
for(ri k = 0; k < (i << 2); k ++) F[(j << 1) + k] = pa[k];
}
}
for(ri i = 0; i < N; i ++) Ib[i] = 0;
In(F, Ib, N); wf(Ib, F, N); b[0] = n;
for(ri i = 1; i <= t; i ++) b[i] = mul(mod - F[i - 1], ivf[i]);
} inline void solve(int n, int m, int t) {
int N = 1, lg = 0;
init(t + t + 5, N, lg);
for(ri i = 0; i < N; i ++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (lg - 1)); NTT(ak, N, 1); NTT(bk, N, 1);
for(ri i = 0; i < N; i ++) ak[i] = mul(ak[i], bk[i]);
NTT(ak, N, -1); int ivnm = fp(mul(n, m), mod - 2);
for(ri i = 1; i <= t; i ++)
printf("%d\n", mul(mul(ak[i], fac[i]), ivnm));
} int main() {
int n = read(), m = read();
rep(i, 1, n) a[i] = read();
rep(i, 1, m) b[i] = read();
Init_Inv(500000);
int t = read();
calc(a, ak, n, t); calc(b, bk, m, t);
solve(n, m, t);
return 0;
}

请无视中间的exp

luoguP4705 玩游戏 分治FFT的更多相关文章

  1. Luogu4705 玩游戏 分治FFT

    传送门 \(\begin{align*} Ans_k &= \sum\limits_{i=1}^n\sum\limits_{j=1}^m (a_i + b_j)^k \\ &= \su ...

  2. luoguP4705 玩游戏

    好好玩 即对于k∈[1,t] 求(ax+by)^k 以下图片均来自于: 在Ta的博客查看 一 二项式展开: 设: 那么: 可以卷积了 二 求: (PS:随机序列的0~k次方和,这是一个经典问题.) 我 ...

  3. 洛谷 P4705 玩游戏 解题报告

    P4705 玩游戏 题意:给长为\(n\)的\(\{a_i\}\)和长为\(m\)的\(\{b_i\}\),设 \[ f(x)=\sum_{k\ge 0}\sum_{i=1}^n\sum_{j=1}^ ...

  4. [题解] Luogu P4721 【模板】分治 FFT

    分治FFT的板子为什么要求逆呢 传送门 这个想法有点\(cdq\)啊,就是考虑分治,在算一段区间的时候,我们把他分成两个一样的区间,然后先做左区间的,算完过后把左区间和\(g\)卷积一下,这样就可以算 ...

  5. 原生JS实战:写了个一边玩游戏,一边记JS的API的游戏

    本文是苏福的原创文章,转载请注明出处:苏福CNblog:http://www.cnblogs.com/susufufu/p/5878913.html 本程序[一边玩游戏,一边记JS的API]是本人的个 ...

  6. bzoj4730: Alice和Bob又在玩游戏

    Description Alice和Bob在玩游戏.有n个节点,m条边(0<=m<=n-1),构成若干棵有根树,每棵树的根节点是该连通块内编号最 小的点.Alice和Bob轮流操作,每回合 ...

  7. BNUOJ 51279[组队活动 Large](cdq分治+FFT)

    传送门 大意:ACM校队一共有n名队员,从1到n标号,现在n名队员要组成若干支队伍,每支队伍至多有m名队员,求一共有多少种不同的组队方案.两个组队方案被视为不同的,当且仅当存在至少一名队员在两种方案中 ...

  8. 小易邀请你玩一个数字游戏,小易给你一系列的整数。你们俩使用这些整数玩游戏。每次小易会任意说一个数字出来,然后你需要从这一系列数字中选取一部分出来让它们的和等于小易所说的数字。 例如: 如果{2,1,2,7}是你有的一系列数,小易说的数字是11.你可以得到方案2+2+7 = 11.如果顽皮的小易想坑你,他说的数字是6,那么你没有办法拼凑出和为6 现在小易给你n个数,让你找出无法从n个数中选取部分求和

    小易邀请你玩一个数字游戏,小易给你一系列的整数.你们俩使用这些整数玩游戏.每次小易会任意说一个数字出来,然后你需要从这一系列数字中选取一部分出来让它们的和等于小易所说的数字. 例如: 如果{2,1,2 ...

  9. cdoj 1136 邱老师玩游戏 树形背包

    邱老师玩游戏 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/problem/show/1136 Desc ...

随机推荐

  1. 压力测试以及编译安装httpd2.4

    压力测试以及编译安装httpd2.4 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.使用 deflate_module模块压缩页面优化传输速度 我们的httpd软件自带的有一个 ...

  2. Python的生成器进阶玩法

    Python的生成器进阶玩法 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.yield的表达式形式 #!/usr/bin/env python #_*_coding:utf-8 ...

  3. IOS的属性和实例变量

    实际上,@property声明的是属性,并不是实例变量.但是编译器会根据属性,自动生成实例变量,和对应的access方法.所以已经在interface里声明了@property,就不再需要在imple ...

  4. JVM调优命令-jstat

    JVM Statistics Monitoring Tool,是用于监视虚拟机运行时状态信息的命令,它可以显示出虚拟机进程中的类装载.内存.垃圾收集.JIT编译等运行数据.[性能分析] 命令格式 1 ...

  5. 流媒体技术学习笔记之(四)解决问题video.js 播放m3u8格式的文件,根据官方的文档添加videojs-contrib-hls也不行的原因解决了

    源码地址:https://github.com/Tinywan/PHP_Experience 总结: 说明: 测试环境:本测试全部来自阿里云直播和OSS存储点播以及本地服务器直播和点播 播放器:Vid ...

  6. 用Java构建一个简单的WebSocket聊天项目之新增HTTP接口调度

    采用框架 我们整个Demo基本不需要大家花费太多时间,就可以实现以下的功能. 用户token登录校验 自我聊天 点对点聊天 群聊 获取在线用户数与用户标签列表 发送系统通知 首先,我们需要介绍一下我们 ...

  7. 为什么今天的L4无人驾驶无法到达终局(转)

    本文来自于公众号驭势未来,是驭势科技的微信公众平台,本博客收录的这篇文章版权作者吴甘沙,博客中仅对部分内容进行编辑. 作者:吴甘沙 原文链接:here 声明:文中的观点只代表版权作者的观点,本转载不涉 ...

  8. Spark笔记之使用UDF(User Define Function)

    一.UDF介绍 UDF(User Define Function),即用户自定义函数,Spark的官方文档中没有对UDF做过多介绍,猜想可能是认为比较简单吧. 几乎所有sql数据库的实现都为用户提供了 ...

  9. perl6 HTTP::UserAgent (2)

    http://www.cnblogs.com/perl6/p/6911166.html 之前这里有个小小例子, 这里只要是总结一下. HTTP::UserAgent包含了以下模块: --------- ...

  10. 有用的linux命令集锦

    http://blog.csdn.net/hackerain/article/details/7946193 1. 查看内存使用情况 free -m 2. 查看系统版本信息 sudo lsb_rele ...