luoguP4721 【模板】分治 FFT (分治NTT)
#include <cstdio>
#include <string>
#include <algorithm>
#include <cstring>
#include <vector>
#define setIO(s) freopen(s".in","r",stdin)
typedef long long ll;
const int maxn=2100005;
const ll mod=998244353;
using namespace std;
inline ll qpow(ll base,ll k) {
ll tmp=1;
for(;k;k>>=1,base=base*base%mod)if(k&1) tmp=tmp*base%mod;
return tmp;
}
inline ll inv(ll a) { return qpow(a, mod-2); }
inline void NTT(ll *a,int len,int flag) {
for(int i=0,k=0;i<len;++i) {
if(i>k) swap(a[i],a[k]);
for(int j=len>>1;(k^=j)<j;j>>=1);
}
for(int mid=1;mid<len;mid<<=1) {
ll wn=qpow(3, (mod-1)/(mid<<1)),x,y;
if(flag==-1) wn=qpow(wn,mod-2);
for(int i=0;i<len;i+=(mid<<1)) {
ll w=1;
for(int j=0;j<mid;++j) {
x=a[i+j],y=w*a[i+j+mid]%mod;
a[i+j]=(x+y)%mod, a[i+j+mid]=(x-y+mod)%mod;
w=w*wn%mod;
}
}
}
if(flag==-1) {
int re=qpow(len,mod-2);
for(int i=0;i<len;++i) a[i]=a[i]*re%mod;
}
}
ll A[maxn],B[maxn];
struct poly {
vector<ll>a;
int len;
poly(){}
inline void clear() { len=0; a.clear(); }
inline void rev() {reverse(a.begin(), a.end()); }
inline void push(int x) { a.push_back(x),++len; }
inline void resize(int x) { len=x; a.resize(x); }
void getinv(poly &b,int n) {
if(n==1) { b.clear(); b.push(inv(a[0])); return; }
getinv(b,n>>1);
int t=n<<1,lim=min(len,n);
for(int i=0;i<lim;++i) A[i]=a[i];
for(int i=lim;i<t;++i) A[i]=0;
for(int i=0;i<b.len;++i) B[i]=b.a[i];
for(int i=b.len;i<t;++i) B[i]=0;
NTT(A,t,1),NTT(B,t,1);
for(int i=0;i<t;++i) A[i]=(2-A[i]*B[i]%mod+mod)*B[i]%mod;
NTT(A,t,-1);
b.clear();
for(int i=0;i<n;++i) b.push(A[i]);
}
poly Inv() {
int n=1;
while(n<=len)n<<=1;
poly b;
b.clear(), getinv(b,n);
return b;
}
poly dao() {
poly c;
c.resize(len);
for(int i=1;i<=len;++i) c.a[i-1]=a[i]*i%mod;
return c;
}
poly jifen() {
poly c;
c.resize(len+1);
for(int i=1;i<=len;++i) c.a[i]=a[i-1]*qpow(i,mod-2)%mod;
c.a[0]=0;
return c;
}
poly Ln() {
poly c=dao()*Inv();
return c.jifen();
}
poly operator * (const poly &b) const {
int n=1;
while(n<=len+b.len) n<<=1;
for(int i=0;i<len;++i) A[i]=a[i];
for(int i=len;i<n;++i) A[i]=0;
for(int i=0;i<b.len;++i) B[i]=b.a[i];
for(int i=b.len;i<n;++i) B[i]=0;
NTT(A,n,1), NTT(B,n,1);
for(int i=0;i<n;++i) A[i]=A[i]*B[i]%mod;
NTT(A,n,-1);
poly c;
c.clear();
for(int i=0;i<len+b.len-1;++i) c.push(A[i]);
return c;
}
poly operator + (const poly &b) const {
poly c;
c.clear();
for(int i=0;i<len;++i) c.push(a[i]);
for(int i=0;i<b.len;++i) {
if(i<len) c.a[i]=(c.a[i]+b.a[i])%mod;
else c.push(b.a[i]);
}
return c;
}
poly operator - (const poly &b) const {
poly c;
c.clear();
for(int i=0;i<len;++i) c.push(a[i]);
for(int i=0;i<b.len;++i) {
if(i<len) c.a[i]=(c.a[i]-b.a[i]+mod)%mod;
else c.push((mod-b.a[i])%mod);
}
return c;
}
friend poly operator / (poly f,poly g) {
poly Q;
int l=f.len-g.len+1;
f.rev(), g.rev(), g.resize(l), f.resize(l);
Q=f*g.Inv(), Q.resize(l), Q.rev();
return Q;
}
friend poly operator % (poly f,poly g) {
poly u=f-(f/g)*g;
u.resize(g.len-1);
return u;
}
}po[4];
ll f[maxn],g[maxn];
inline void inv() {
int n,x;
scanf("%d",&n), po[0].clear();
for(int i=0;i<n;++i) scanf("%d",&x), po[0].push(x);
po[1]=po[0].Inv();
for(int i=0;i<po[1].len;++i) printf("%lld ",po[1].a[i]);
}
inline void mult() {
int n,m,x;
scanf("%d%d",&n,&m);
for(int i=0;i<=n;++i) scanf("%d",&x), po[0].push(x);
for(int i=0;i<=m;++i) scanf("%d",&x), po[1].push(x);
po[1]=po[0]*po[1];
for(int i=0;i<po[1].len;++i) printf("%lld ",po[1].a[i]);
}
inline void divide() {
int n,m,x;
scanf("%d%d",&n,&m);
for(int i=0;i<=n;++i) scanf("%d",&x), po[0].push(x);
for(int i=0;i<=m;++i) scanf("%d",&x), po[1].push(x);
po[2]=po[0]/po[1];
for(int i=0;i<po[2].len;++i) printf("%lld ",po[2].a[i]);
printf("\n");
po[2]=po[0]%po[1];
for(int i=0;i<po[2].len;++i) printf("%lld ",po[2].a[i]);
}
inline void Ln() {
int n,x;
scanf("%d",&n);
for(int i=0;i<n;++i) scanf("%d",&x), po[0].push(x);
po[0]=po[0].Ln();
for(int i=0;i<n;++i) printf("%lld ",po[0].a[i]);
}
inline void CDQ_NTT(int l,int r) {
if(l==r) return;
int mid=(l+r)>>1;
CDQ_NTT(l,mid);
po[0].clear(),po[1].clear();
for(int i=l;i<=mid;++i) po[0].push(f[i]);
for(int i=0;i<=r-l;++i) po[1].push(g[i]);
po[0]=po[0]*po[1];
for(int i=mid+1;i<=r;++i) f[i]+=po[0].a[i-l],f[i]%=mod;
CDQ_NTT(mid+1,r);
}
inline void CDQ() {
int n;
scanf("%d",&n);
for(int i=1;i<n;++i) scanf("%lld",&g[i]);
f[0]=1ll;
CDQ_NTT(0,n-1);
for(int i=0;i<n;++i) printf("%lld ",f[i]);
}
int main() {
// setIO("input");
CDQ();
return 0;
}
再来以个多项式求逆版本的~
code:
#include <bits/stdc++.h>
#define ll long long
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
const int G=3,mod=998244353,N=800003;
int A[N],B[N];
inline int qpow(int x,int y)
{
int tmp=1;
for(;y;y>>=1,x=1ll*x*x%mod) if(y&1) tmp=1ll*tmp*x%mod;
return tmp;
}
inline int INV(int x) { return qpow(x,mod-2); }
void NTT(int *a,int len,int flag)
{
int i,j,k,mid;
for(i=k=0;i<len;++i)
{
if(i>k) swap(a[i],a[k]);
for(j=len>>1;(k^=j)<j;j>>=1);
}
for(mid=1;mid<len;mid<<=1)
{
int wn=qpow(G,(mod-1)/(mid<<1));
if(flag==-1) wn=INV(wn);
for(i=0;i<len;i+=mid<<1)
{
int w=1;
for(j=0;j<mid;++j)
{
int x=a[i+j],y=1ll*w*a[i+j+mid]%mod;
a[i+j]=1ll*(x+y)%mod, a[i+j+mid]=1ll*(x-y+mod)%mod;
w=1ll*w*wn%mod;
}
}
}
if(flag==-1)
{
int rev=INV(len);
for(i=0;i<len;++i) a[i]=1ll*a[i]*rev%mod;
}
}
void getinv(int *a,int *b,int len)
{
if(len==1) { b[0]=INV(a[0]); return; }
getinv(a,b,len>>1);
for(int i=0;i<len;++i) A[i]=a[i], B[i]=b[i];
NTT(A,len<<1,1),NTT(B,len<<1,1);
for(int i=0;i<(len<<1);++i) A[i]=1ll*A[i]*B[i]%mod*B[i]%mod;
NTT(A,len<<1,-1);
for(int i=0;i<len;++i) b[i]=((b[i]<<1)%mod-A[i]+mod)%mod;
}
int f[N],g[N],h[N],tmp[N];
int main()
{
setIO("input");
int i,j,n;
scanf("%d",&n);
for(i=1;i<=n-1;++i) scanf("%d",&g[i]);
int lim=1;
while(lim<=2*n) lim<<=1;
h[0]=1;
for(i=1;i<=n-1;++i) h[i]=mod-g[i];
getinv(h,tmp,lim);
for(i=n;i<lim;++i) tmp[i]=0;
NTT(g,lim,1);
NTT(tmp,lim,1);
for(i=0;i<lim;++i) g[i]=1ll*g[i]*tmp[i]%mod;
NTT(g,lim,-1);
g[0]=1;
for(i=0;i<n;++i) printf("%d ",g[i]);
return 0;
}
luoguP4721 【模板】分治 FFT (分治NTT)的更多相关文章
- 洛谷 4721 【模板】分治 FFT——分治FFT / 多项式求逆
题目:https://www.luogu.org/problemnew/show/P4721 分治FFT:https://www.cnblogs.com/bztMinamoto/p/9749557.h ...
- 洛谷 P4721 [模板]分治FFT —— 分治FFT / 多项式求逆
题目:https://www.luogu.org/problemnew/show/P4721 分治做法,考虑左边对右边的贡献即可: 注意最大用到的 a 的项也不过是 a[r-l] ,所以 NTT 可以 ...
- 2017 3 11 分治FFT
考试一道题的递推式为$$f[i]=\sum_{j=1}^{i} j^k \times (i-1)! \times \frac{f[i-j]}{(i-j)!}$$这显然是一个卷积的形式,但$f$需要由自 ...
- hdu5730 Shell Necklace 【分治fft】
题目 简述: 有一段长度为n的贝壳,将其划分为若干段,给出划分为每种长度的方案数,问有多少种划分方案 题解 设\(f[i]\)表示长度为\(i\)时的方案数 不难得dp方程: \[f[i] = \su ...
- 洛谷.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 ...
- luoguP4721 【模板】分治 FFT
P4721 [模板]分治 FFT 链接 luogu 题目描述 给定长度为 \(n-1\) 的数组 \(g[1],g[2],..,g[n-1]\),求 \(f[0],f[1],..,f[n-1]\),其 ...
- 洛谷 P4721 【模板】分治 FFT 解题报告
P4721 [模板]分治 FFT 题目背景 也可用多项式求逆解决. 题目描述 给定长度为 \(n−1\) 的数组 \(g[1],g[2],\dots,g[n-1]\),求 \(f[0],f[1],\d ...
- 【洛谷4721】【模板】分治FFT(CDQ分治_NTT)
题目: 洛谷 4721 分析: 我觉得这个 "分治 FFT " 不能算一种特殊的 FFT ,只是 CDQ 分治里套了个用 FFT (或 NTT)计算的过程,二者是并列关系而不是偏正 ...
- FTT & NTT & 分治FFT
FFT study from: http://www.orchidany.cf/2019/02/19/FFT1/ https://www.cnblogs.com/zwfymqz/p/8244902.h ...
随机推荐
- 阶段1 语言基础+高级_1-3-Java语言高级_1-常用API_1_第8节 Math类_18_数学工具类Math
常用几个数学的方法 abs绝对值 ceil向上取整,它并不是四舍五入 floor向下取整 round四舍五入 PI 按住Ctrl+鼠标左键 进入Math这个类的源码里面 Ctrl+F12 然后输入PI ...
- try...catch语句
程序的异常:Throwable 严重问题Error我们不处理,这种问题一般都是很严重的,比如内存溢出 问题Exception 编译期问题不是RuntimeException的异常必须进行处理,如果不处 ...
- python 操作openpyxl导出Excel 设置单元格格式以及合并处理
贴上一个例子,里面设计很多用法,根据将相同日期的某些行合并处理. from openpyxl import Workbook from openpyxl.styles import Font, Fil ...
- Java ——JDBC数据库编程
数据库分类 关系型数据库:以表来存放数据的,数据与数据之间的关系通过表之间的连接体现 面向对象的数据库:保存的是对象本身 其它 数据库:数据库管理系统中创建一个个的保存数据的单位 数据是保存在数据库的 ...
- 阅读jdk源码的流程(从今天开始要阅读jdk源码)
1.java.lang 2.java.util 3.java.util.concurrent 4.java.util.concurrent.atomic 5.java.lang.reflect 6.j ...
- Hyperledger:Fabric CA 用户指南 [译]
Fabric CA 用户指南 Fabric CA 是 Hyperledger Fabric 的官方配套认证设施. 原文链接:http://hyperledger-fabric.readthedocs. ...
- leveldb memtable
memtable常驻于内存,需要按照key进行排序,通常意义上的话,可以使用二叉查找树来实现,跟进一步可以使用红黑树保证树的平衡,但是leveldb中使用了另外的一种数据结构:跳表Skip List. ...
- The Log-Structured Merge-Tree(译)
coming from http://duanple.blog.163.com/blog/static/7097176720120391321283/
- Redis 21问,你接得住不?
作者:菜鸟小于 cnblogs.com/Young111/p/11518346.html 1.什么是redis? Redis 是一个基于内存的高性能key-value数据库. 2.Reids的特点 R ...
- python学习笔记(7)容器以及容器的访问使用
一.容器 1.list列表 序列是python中最基本的数据结构,序列中的每个元素都分配一个数字,它的位置或索引,第一个索引是0,第二个索引是1,以此类推 Built-in mutable seque ...