题目:https://www.luogu.org/problemnew/show/P4721

分治做法,考虑左边对右边的贡献即可;

注意最大用到的 a 的项也不过是 a[r-l] ,所以 NTT 可以只做到 2*(r-l),能快一倍。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int const xn=(<<),mod=;
int n,f[xn],g[xn],a[xn],b[xn],rev[xn];
int rd()
{
int ret=,f=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=; ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return f?ret:-ret;
}
ll pw(ll a,int b)
{
ll ret=;
for(;b;b>>=,a=(a*a)%mod)if(b&)ret=(ret*a)%mod;
return ret;
}
int upt(int x){while(x>=mod)x-=mod; while(x<)x+=mod; return x;}
void ntt(int *a,int tp,int lim)
{
for(int i=;i<lim;i++)
if(i<rev[i])swap(a[i],a[rev[i]]);
for(int mid=;mid<lim;mid<<=)
{
int wn=pw(,tp==?(mod-)/(mid<<):(mod-)-(mod-)/(mid<<));
for(int j=,len=(mid<<);j<lim;j+=len)
for(int k=,w=;k<mid;k++,w=(ll)w*wn%mod)
{
int x=a[j+k],y=(ll)w*a[j+mid+k]%mod;
a[j+k]=upt(x+y); a[j+mid+k]=upt(x-y);
}
}
if(tp==)return; int inv=pw(lim,mod-);
for(int i=;i<lim;i++)a[i]=(ll)a[i]*inv%mod;
}
void work(int l,int r)
{
if(l==r)return;
int len=r-l+,mid=((l+r)>>);
work(l,mid); int lim=,L=;
while(lim<=(r-l))lim<<=,L++;//max:r-l
for(int i=;i<lim;i++)rev[i]=((rev[i>>]>>)|((i&)<<(L-)));
for(int i=;i<lim;i++)a[i]=b[i]=;//
for(int i=l;i<=mid;i++)a[i-l]=f[i];
for(int i=;i<len;i++)b[i]=g[i];
ntt(a,,lim); ntt(b,,lim);
for(int i=;i<lim;i++)a[i]=(ll)a[i]*b[i]%mod;
ntt(a,-,lim);
for(int i=mid+;i<=r;i++)f[i]=upt(f[i]+a[i-l]);
work(mid+,r);
}
int main()
{
n=rd(); f[]=;
for(int i=;i<n;i++)g[i]=rd();
work(,n-);
for(int i=;i<n;i++)printf("%d ",f[i]); puts("");
return ;
}

多项式求逆做法感觉很妙:

设 \( F(x) = \sum f_{i}*x_{i} \),\( G(x) = \sum g_{i}*x_{i} \)

则 \( F(x) * G(x) = \sum x_{i} * \sum\limits_{j=0}^{i} f_{j}*g_{i-j} \)

即 \( F(x) * G(x) = F(x) - f_{0}*x_{0} \)

所以 \( F(x) = (1-G(x))^{-1} \)

多项式求逆即可。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int const xn=(<<),mod=;
int n,f[xn],g[xn],c[xn],rev[xn];
int rd()
{
int ret=,f=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=; ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return f?ret:-ret;
}
ll pw(ll a,int b)
{
ll ret=;
for(;b;b>>=,a=(a*a)%mod)if(b&)ret=(ret*a)%mod;
return ret;
}
int upt(int x){while(x>=mod)x-=mod; while(x<)x+=mod; return x;}
void ntt(int *a,int tp,int lim)
{
for(int i=;i<lim;i++)
if(i<rev[i])swap(a[i],a[rev[i]]);
for(int mid=;mid<lim;mid<<=)
{
int p=mod-,len=(mid<<),wn=pw(,tp==?p/len:p-p/len);
for(int j=;j<lim;j+=len)
for(int k=,w=;k<mid;k++,w=(ll)w*wn%mod)
{
int x=a[j+k],y=(ll)w*a[j+mid+k]%mod;
a[j+k]=upt(x+y); a[j+mid+k]=upt(x-y);
}
}
if(tp==)return; int inv=pw(lim,mod-);
for(int i=;i<lim;i++)a[i]=(ll)a[i]*inv%mod;
}
void inv(int *a,int *b,int n)
{
if(n==){b[]=pw(a[],mod-); return;}
inv(a,b,(n+)>>);
int lim=,l=;
while(lim<n+n)lim<<=,l++;
for(int i=;i<lim;i++)rev[i]=((rev[i>>]>>)|((i&)<<(l-)));
for(int i=;i<n;i++)c[i]=a[i];
for(int i=n;i<lim;i++)c[i]=;
ntt(c,,lim); ntt(b,,lim);
for(int i=;i<lim;i++)b[i]=((ll)-(ll)c[i]*b[i])%mod*b[i]%mod;
ntt(b,-,lim);
for(int i=n;i<lim;i++)b[i]=;
}
int main()
{
n=rd(); f[]=; g[]=;
for(int i=;i<n;i++)g[i]=-rd();
inv(g,f,n);
for(int i=;i<n;i++)printf("%d ",f[i]); puts("");
return ;
}

洛谷 P4721 [模板]分治FFT —— 分治FFT / 多项式求逆的更多相关文章

  1. 洛谷P3711 仓鼠的数学题(伯努利数+多项式求逆)

    题面 传送门 题解 如果您不知道伯努利数是什么可以去看看这篇文章 首先我们把自然数幂和化成伯努利数的形式 \[\sum_{i=1}^{n-1}i^k={1\over k+1}\sum_{i=0}^k{ ...

  2. 洛谷P4721 【模板】分治 FFT(生成函数+多项式求逆)

    传送门 我是用多项式求逆做的因为分治FFT看不懂…… upd:分治FFT的看这里 话说这个万恶的生成函数到底是什么东西…… 我们令$F(x)=\sum_{i=0}^\infty f_ix^i,G(x) ...

  3. BZOJ 4555: [Tjoi2016&Heoi2016]求和 [分治FFT 组合计数 | 多项式求逆]

    4555: [Tjoi2016&Heoi2016]求和 题意:求\[ \sum_{i=0}^n \sum_{j=0}^i S(i,j)\cdot 2^j\cdot j! \\ S是第二类斯特林 ...

  4. NOIP 2013 洛谷P1966 火柴排队 (树状数组求逆序对)

    对于a[],b[]两个数组,我们应选取其中一个为基准,再运用树状数组求逆序对的方法就行了. 大佬博客:https://www.cnblogs.com/luckyblock/p/11482130.htm ...

  5. 多项式求逆元详解+模板 【洛谷P4238】多项式求逆

    概述 多项式求逆元是一个非常重要的知识点,许多多项式操作都需要用到该算法,包括多项式取模,除法,开跟,求ln,求exp,快速幂.用快速傅里叶变换和倍增法可以在$O(n log n)$的时间复杂度下求出 ...

  6. 洛谷 P4721 【模板】分治 FFT 解题报告

    P4721 [模板]分治 FFT 题目背景 也可用多项式求逆解决. 题目描述 给定长度为 \(n−1\) 的数组 \(g[1],g[2],\dots,g[n-1]\),求 \(f[0],f[1],\d ...

  7. 洛谷P4721 【模板】分治 FFT(分治FFT)

    传送门 多项式求逆的解法看这里 我们考虑用分治 假设现在已经求出了$[l,mid]$的答案,要计算他们对$[mid+1,r]$的答案的影响 那么对右边部分的点$f_x$的影响就是$f_x+=\sum_ ...

  8. 洛谷.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 ...

  9. [洛谷P3806] [模板] 点分治1

    洛谷 P3806 传送门 这个点分治都不用减掉子树里的了,直接搞就行了. 注意第63行 if(qu[k]>=buf[j]) 不能不写,也不能写成>. 因为这个WA了半天...... 如果m ...

随机推荐

  1. smokeping安装

    一.准备工作: 1.以防止安装依赖出错,首先给系统安装第三方源:rpm -Uvh http://apt.sw.be/redhat/el6/en/x86_64/rpmforge/RPMS/rpmforg ...

  2. javascript onclick中post提交

    对post提交进行封装: function post(URL, PARAMS) { var temp = document.createElement("form"); temp. ...

  3. Socket的UDP协议在erlang中的实现

    现在我们看看UDP协议(User Datagram Protocol,用户数据报协议).使用UDP,互联网上的机器之间可以互相发送小段的数据,叫做数据报.UDP数据报是不可靠的,这意味着如果客户端发送 ...

  4. arcgis10.0 切片并发布服务及验证

    1.切片参考网址:https://jingyan.baidu.com/article/fa4125accc6bef28ac7092d7.html 2.通过下面代码验证  参考网址https://www ...

  5. 【PHP开发】ThinkPHP3.1.3问题集及解决方法

    Outline: 无法获取post请求中的url参数的问题 中文存入数据表后为空字符串 1. 无法获取post请求中的url参数的问题 ThinkPHP3.1.3中,如果提交的post请求中,如果要在 ...

  6. html 锚点定位

    在html中设置锚点定位我知道的有几种方法.在此和大家分享一下: 1.使用id定位: <a href="#1F" name="1F">锚点1< ...

  7. UITableView使用指南

    本文转载至 http://blog.csdn.net/yu0089/article/details/8227402 一.概述 UITableView是iOS开发比不可少也是最重要的一个控件类.可以说任 ...

  8. 九度OJ 1056:最大公约数 (GCD)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:6278 解决:4075 题目描述: 输入两个正整数,求其最大公约数. 输入: 测试数据有多组,每组输入两个正整数. 输出: 对于每组输入,请 ...

  9. python网络爬虫之初识网络爬虫

    第一次接触到python是一个很偶然的因素,由于经常在网上看连载小说,很多小说都是上几百的连载.因此想到能不能自己做一个工具自动下载这些小说,然后copy到电脑或者手机上,这样在没有网络或者网络信号不 ...

  10. PHP Framework

    PHP Framework is built for PHP developers who need elegant toolkit to create full-featured web appli ...