[洛谷P4721]【模板】分治 FFT
题目大意:给定长度为$n-1$的数组$g_{[1,n)}$,求$f_{[0,n)}$,要求:
$$
f_i=\sum_{j=1}^if_{i-j}g_j\\
f_0=1
$$
题解:直接求复杂度是$O(n^2)$,明显不可以通过此题
分治$FFT$,可以用$CDQ$分治,先求出$f_{[l,mid)}$,可以发现这部分对区间的$f_{[mid,r)}$的贡献是$f_{[l,mid)}*g_{[0,r-l)}$,卷出来加到对应位置就行了,复杂度$O(n\log_2^2n)$
卡点:无
C++ Code:
#include <algorithm>
#include <cstdio>
#include <cctype>
namespace std {
struct istream {
#define M (1 << 21 | 3)
char buf[M], *ch = buf - 1;
inline istream() {
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
#endif
fread(buf, 1, M, stdin);
}
inline istream& operator >> (int &x) {
while (isspace(*++ch));
for (x = *ch & 15; isdigit(*++ch); ) x = x * 10 + (*ch & 15);
return *this;
}
#undef M
} cin;
struct ostream {
#define M (1 << 21 | 3)
char buf[M], *ch = buf - 1;
int w;
inline ostream& operator << (int x) {
if (!x) {
*++ch = '0';
return *this;
}
for (w = 1; w <= x; w *= 10);
for (w /= 10; w; w /= 10) *++ch = (x / w) ^ 48, x %= w;
return *this;
}
inline ostream& operator << (const char x) {*++ch = x; return *this;}
inline ~ostream() {
#ifndef ONLINE_JUDGE
freopen("output.txt", "w", stdout);
#endif
fwrite(buf, 1, ch - buf + 1, stdout);
}
#undef M
} cout;
} #define maxn 131072 | 3
const int mod = 998244353, G = 3; namespace Math {
inline int pw(int base, int p) {
static int res;
for (res = 1; p; p >>= 1, base = static_cast<long long> (base) * base % mod) if (p & 1) res = static_cast<long long> (res) * base % mod;
return res;
}
inline int inv(int x) {return pw(x, mod - 2);}
} int n;
int f[maxn], g[maxn];
namespace Poly {
#define N 131072 | 3
int s, lim, ilim, rev[N];
int Wn[N + 1];
inline void reduce(int &x) {x += x >> 31 & mod;}
inline void clear(register int *l, const int *r) {
if (l >= r) return ;
while (l != r) *l++ = 0;
}
inline void init(const int n) {
s = -1, lim = 1; while (lim <= n) lim <<= 1, s++; ilim = Math::inv(lim);
for (int i = 1; i < lim; i++) rev[i] = rev[i >> 1] >> 1 | (i & 1) << s;
const int t = Math::pw(G, (mod - 1) / lim);
*Wn = 1; for (register int *i = Wn; i != Wn + lim; ++i) *(i + 1) = static_cast<long long> (*i) * t % mod;
} inline void NTT(int *A, const int op = 1) {
for (register int i = 1; i < lim; i++) if (i < rev[i]) std::swap(A[i], A[rev[i]]);
for (register int mid = 1; mid < lim; mid <<= 1) {
const int t = lim / mid >> 1;
for (register int i = 0; i < lim; i += mid << 1) {
for (register int j = 0; j < mid; j++) {
const int W = op ? Wn[t * j] : Wn[lim - t * j];
const int X = A[i + j], Y = static_cast<long long> (A[i + j + mid]) * W % mod;
reduce(A[i + j] += Y - mod), reduce(A[i + j + mid] = X - Y);
}
}
}
if (!op) for (int i = 0; i < lim; i++) A[i] = static_cast<long long> (A[i]) * ilim % mod;
} int A[N], B[N];
void CDQ_NTT(const int l, const int r) {
if (r - l < 2) return ;
const int mid = l + r >> 1;
CDQ_NTT(l, mid); init(r - l);
std::copy(f + l, f + mid, A); clear(A + mid - l, A + lim);
std::copy(g, g + r - l, B); clear(B + r - l, B + lim);
NTT(A), NTT(B);
for (int i = 0; i < lim; i++) A[i] = static_cast<long long> (A[i]) * B[i] % mod;
NTT(A, 0);
for (int i = mid; i < r; i++) reduce(f[i] += A[i - l] - mod);
CDQ_NTT(mid, r);
}
#undef N
} int main() {
std::cin >> n;
for (int i = 1; i < n; i++) std::cin >> g[i];
*f = 1;
Poly::CDQ_NTT(0, n);
for (int i = 0; i < n; i++) std::cout << f[i] << ' ';
std::cout << '\n';
return 0;
}
[洛谷P4721]【模板】分治 FFT的更多相关文章
- 洛谷 P4721 [模板]分治FFT —— 分治FFT / 多项式求逆
题目:https://www.luogu.org/problemnew/show/P4721 分治做法,考虑左边对右边的贡献即可: 注意最大用到的 a 的项也不过是 a[r-l] ,所以 NTT 可以 ...
- 洛谷.4721.[模板]分治FFT(NTT)
题目链接 换一下形式:\[f_i=\sum_{j=0}^{i-1}f_jg_{i-j}\] 然后就是分治FFT模板了\[f_{i,i\in[mid+1,r]}=\sum_{j=l}^{mid}f_jg ...
- 解题:洛谷4721 [模板]分治FFT
题面 这是CDQ入门题,不要被题目名骗了,这核心根本不在不在FFT上啊=.= 因为后面的项的计算依赖于前面的项,不能直接FFT.所以用CDQ的思想,算出前面然后考虑给后面的贡献 #include< ...
- 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)
To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...
- 洛谷 P4721 【模板】分治 FFT 解题报告
P4721 [模板]分治 FFT 题目背景 也可用多项式求逆解决. 题目描述 给定长度为 \(n−1\) 的数组 \(g[1],g[2],\dots,g[n-1]\),求 \(f[0],f[1],\d ...
- 洛谷P4721 【模板】分治 FFT(分治FFT)
传送门 多项式求逆的解法看这里 我们考虑用分治 假设现在已经求出了$[l,mid]$的答案,要计算他们对$[mid+1,r]$的答案的影响 那么对右边部分的点$f_x$的影响就是$f_x+=\sum_ ...
- 洛谷P4721 【模板】分治 FFT(生成函数+多项式求逆)
传送门 我是用多项式求逆做的因为分治FFT看不懂…… upd:分治FFT的看这里 话说这个万恶的生成函数到底是什么东西…… 我们令$F(x)=\sum_{i=0}^\infty f_ix^i,G(x) ...
- [洛谷P4721]【模板】分治 FFT_求逆
题目大意:给定长度为$n-1$的数组$g_{[1,n)}$,求$f_{[0,n)}$,要求: $$f_i=\sum_{j=1}^if_{i-j}g_j\\f_0=1$$ 题解:分治$FFT$博客,发现 ...
- POJ 1741.Tree and 洛谷 P4178 Tree-树分治(点分治,容斥版) +二分 模板题-区间点对最短距离<=K的点对数量
POJ 1741. Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 34141 Accepted: 11420 ...
随机推荐
- 4、Java并发编程:synchronized
Java并发编程:synchronized 虽然多线程编程极大地提高了效率,但是也会带来一定的隐患.比如说两个线程同时往一个数据库表中插入不重复的数据,就可能会导致数据库中插入了相同的数据.今天我们就 ...
- 创龙DSP6748学习之RS485收发
1. 先看下原理图,第一个问题,RS485其实就是使用的串口USART1,同时485的输出脚之间接120欧姆的电阻. 遇到个问题,为什么有两个使能引脚?还有RS485_A和RS485_B为什么分别接上 ...
- nginx 路由配置
nginx中location对url匹配: 语法:location [=|~|~*|^~] /uri/ { … } 当匹配中符合条件的location,则执行内部指令:如果使用正则表达式,必须使用~* ...
- ThinkPHP开启设置子域名笔记
一.ThinkPHP框架里 common下的config文件 'APP_SUB_DOMAIN_DEPLOY' => 1, // 开启子域名配置 'APP_SUB_DOMAIN_RULES' =& ...
- Qt 报错onecoreuap\inetcore\urlmon\zones\zoneidentifier.cxx(359)\urlmon.dll!00007FF9D9FA5B50:
具体报错内容 onecoreuap\inetcore\urlmon\zones\zoneidentifier.cxx(359)\urlmon.dll!00007FF9D9FA5B50: (caller ...
- python内建模块Collections
# -*- coding:utf-8 -*- # OrderedDict可以实现一个FIFO(先进先出)的dict, # 当容量超出限制时,先删除最早添加的Key: from collections ...
- 如何处理 jQuery $(window).resize() 中的方法被多次执行的小问题
引言: 估计很多同志们在编写浏览器resize()的方法时,都会遇到这样的情况: 当拖动浏览器的边角时,页面中的一些效果随浏览器大小的改变而触发,这一过程开始到结束,resize() 中的方法被执行了 ...
- Ubuntu16.04安装truffle时的一些错误
1.使用truffle时出现 Error: /usr/bin/env: node: 没有那个文件或目录 1.如果是用sudo apt-get install nodejs命令安装的nodejs, ub ...
- HDU 1569 方格取数(2)(最大流最小割の最大权独立集)
Description 给你一个m*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的数的和最大. ...
- 《javascript模式--by Stoyan Stefanov》书摘--字面量和构造函数
二.字面量和构造函数 1,能够使用对象字面量时,就没理由使用new Object构造函数 // 一个空对象var 0 = new Object();console.log( o.constructor ...