[洛谷P4721]【模板】分治 FFT_求逆
题目大意:给定长度为$n-1$的数组$g_{[1,n)}$,求$f_{[0,n)}$,要求:
$$
f_i=\sum_{j=1}^if_{i-j}g_j\\
f_0=1
$$
题解:分治$FFT$博客,发现这道题就是求$f*g=f-1$($f-1$就是没有常数项的$f$),改写一下式子:
$$
f*g\equiv f-1\pmod{x^n}\\
f-f*g\equiv1\pmod{x^n}\\
f*(1-g)\equiv1\pmod{x^n}\\
f\equiv(1-g)^{-1}\pmod{x^n}
$$
卡点:无
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;
} 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);}
} inline void reduce(int &a) {a += a >> 31 & mod;}
inline long long get_reducell(long long a) {return a += a >> 63 & mod;}
namespace Poly {
#define N (262144 | 3)
int lim, ilim, s, rev[N];
int Wn[N + 1];
inline void init(int n) {
s = -1, lim = 1; while (lim <= n) lim <<= 1, s++; ilim = Math::inv(lim);
for (register 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 clear(register int *l, const int *r) {
if (l >= r) return ;
while (l != r) *l++ = 0;
} 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 (register int *i = A; i != A + lim; ++i) *i = static_cast<long long> (*i) * ilim % mod;
} int C[N];
void INV(int *A, int *B, int n) {
if (n == 1) {*B = Math::inv(*A); return ;}
INV(A, B, n + 1 >> 1);
init(n + n - 1);
std::copy(A, A + n, C); clear(C + n, C + lim);
NTT(B), NTT(C);
for (register int i = 0; i < lim; i++) B[i] = (2 - static_cast<long long> (B[i]) * C[i] % mod + mod) % mod * B[i] % mod;
NTT(B, 0), clear(B + n, B + lim);
}
#undef N
} #define maxn (262144 | 3)
int n, f[maxn], g[maxn]; int main() {
std::cin >> n;
*g = 1;
for (int i = 1; i < n; i++) {
std::cin >> g[i];
g[i] = mod - g[i];
}
Poly::INV(g, f, 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 ...
- 洛谷P4841 城市规划(生成函数 多项式求逆)
题意 链接 Sol Orz yyb 一开始想的是直接设\(f_i\)表示\(i\)个点的无向联通图个数,枚举最后一个联通块转移,发现有一种情况转移不到... 正解是先设\(g(n)\)表示\(n\)个 ...
- 解题:洛谷4721 [模板]分治FFT
题面 这是CDQ入门题,不要被题目名骗了,这核心根本不在不在FFT上啊=.= 因为后面的项的计算依赖于前面的项,不能直接FFT.所以用CDQ的思想,算出前面然后考虑给后面的贡献 #include< ...
- 洛谷P4841 城市规划(多项式求逆)
传送门 这题太珂怕了……如果是我的话完全想不出来…… 题解 //minamoto #include<iostream> #include<cstdio> #include< ...
- 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)
To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...
- 洛谷P4721 【模板】分治 FFT(生成函数+多项式求逆)
传送门 我是用多项式求逆做的因为分治FFT看不懂…… upd:分治FFT的看这里 话说这个万恶的生成函数到底是什么东西…… 我们令$F(x)=\sum_{i=0}^\infty f_ix^i,G(x) ...
- 洛谷 P4721 【模板】分治 FFT 解题报告
P4721 [模板]分治 FFT 题目背景 也可用多项式求逆解决. 题目描述 给定长度为 \(n−1\) 的数组 \(g[1],g[2],\dots,g[n-1]\),求 \(f[0],f[1],\d ...
- 洛谷P4238【模板】多项式求逆
洛谷P4238 多项式求逆:http://blog.miskcoo.com/2015/05/polynomial-inverse 注意:直接在点值表达下做$B(x) \equiv 2B'(x) - A ...
随机推荐
- Please ensure JDK installation is valid and compatible with the current OS
报错如下: Gradle sync failed: Could not run JVM from the selected JDK. Please ensure JDK installation is ...
- GitLab 自动触发 Jenkins 构建
GitLab 是当前应用非常广泛的 Git Hosting 工具,Jenkins 是非常牛逼的持续集成工具.尽管 GitLab 有内建的 GitLab CI,但它远没有 Jenkins 那么强大好用. ...
- Chromium添加一段新字符串
参考:https://groups.google.com/a/chromium.org/forum/#!searchin/chromium-dev/tclib%7Csort:relevance/chr ...
- Linux命令应用大词典-第13章 用户和组群管理
13.1 useradd:创建用户账户 13.2 adduser:创建用户账户 13.3 lnewusers:创建用户账户 13.4 usermod:修改用户账户 13.5 userdel:删除用户账 ...
- 【jmeter进阶之逻辑控制器】
jmeter进阶之逻辑控制器 转载 https://www.cnblogs.com/malinalian/p/10491946.html 常用的逻辑控制器 1,循环控制器:可以设置该控制器内 ...
- ELK部署方法
最近经理开会说公司要安装ELK日志管理让我们搭建ELK,下面是我搭建步骤和流程,用三台机测试机器搭建的. 软件包我都 给你们放/usr/local/src/elk目录下安装目录都放在/usr/loca ...
- docker 命令笔记
docker images 查看镜像 docker search 查找镜像 docker pull 拉取镜像 docker push 推送镜像 docker ps 查看正在运行的容器 docker p ...
- 剑指offer-包含min函数的栈20
题目描述 定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1)). class Solution: def __init__(self): self.st ...
- [堆+贪心]牛客练习赛40-B
传送门:牛客练习赛40 题面: 小A手头有 n 份任务,他可以以任意顺序完成这些任务,只有完成当前的任务后,他才能做下一个任务 第 i 个任务需要花费 x_i 的时间,同时完成第 i 个任务的时间不 ...
- POJ 2177 Ghost Busters(三维几何)
Description The famous Ghost Busters team has decided to upgrade their Ectomobile (aka Ecto-1) with ...