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

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

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

代码如下:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. using namespace std;
  6. typedef long long ll;
  7. int const xn=(<<),mod=;
  8. int n,f[xn],g[xn],a[xn],b[xn],rev[xn];
  9. int rd()
  10. {
  11. int ret=,f=; char ch=getchar();
  12. while(ch<''||ch>''){if(ch=='-')f=; ch=getchar();}
  13. while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
  14. return f?ret:-ret;
  15. }
  16. ll pw(ll a,int b)
  17. {
  18. ll ret=;
  19. for(;b;b>>=,a=(a*a)%mod)if(b&)ret=(ret*a)%mod;
  20. return ret;
  21. }
  22. int upt(int x){while(x>=mod)x-=mod; while(x<)x+=mod; return x;}
  23. void ntt(int *a,int tp,int lim)
  24. {
  25. for(int i=;i<lim;i++)
  26. if(i<rev[i])swap(a[i],a[rev[i]]);
  27. for(int mid=;mid<lim;mid<<=)
  28. {
  29. int wn=pw(,tp==?(mod-)/(mid<<):(mod-)-(mod-)/(mid<<));
  30. for(int j=,len=(mid<<);j<lim;j+=len)
  31. for(int k=,w=;k<mid;k++,w=(ll)w*wn%mod)
  32. {
  33. int x=a[j+k],y=(ll)w*a[j+mid+k]%mod;
  34. a[j+k]=upt(x+y); a[j+mid+k]=upt(x-y);
  35. }
  36. }
  37. if(tp==)return; int inv=pw(lim,mod-);
  38. for(int i=;i<lim;i++)a[i]=(ll)a[i]*inv%mod;
  39. }
  40. void work(int l,int r)
  41. {
  42. if(l==r)return;
  43. int len=r-l+,mid=((l+r)>>);
  44. work(l,mid); int lim=,L=;
  45. while(lim<=(r-l))lim<<=,L++;//max:r-l
  46. for(int i=;i<lim;i++)rev[i]=((rev[i>>]>>)|((i&)<<(L-)));
  47. for(int i=;i<lim;i++)a[i]=b[i]=;//
  48. for(int i=l;i<=mid;i++)a[i-l]=f[i];
  49. for(int i=;i<len;i++)b[i]=g[i];
  50. ntt(a,,lim); ntt(b,,lim);
  51. for(int i=;i<lim;i++)a[i]=(ll)a[i]*b[i]%mod;
  52. ntt(a,-,lim);
  53. for(int i=mid+;i<=r;i++)f[i]=upt(f[i]+a[i-l]);
  54. work(mid+,r);
  55. }
  56. int main()
  57. {
  58. n=rd(); f[]=;
  59. for(int i=;i<n;i++)g[i]=rd();
  60. work(,n-);
  61. for(int i=;i<n;i++)printf("%d ",f[i]); puts("");
  62. return ;
  63. }

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

设 \( 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} \)

多项式求逆即可。

代码如下:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. using namespace std;
  6. typedef long long ll;
  7. int const xn=(<<),mod=;
  8. int n,f[xn],g[xn],c[xn],rev[xn];
  9. int rd()
  10. {
  11. int ret=,f=; char ch=getchar();
  12. while(ch<''||ch>''){if(ch=='-')f=; ch=getchar();}
  13. while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
  14. return f?ret:-ret;
  15. }
  16. ll pw(ll a,int b)
  17. {
  18. ll ret=;
  19. for(;b;b>>=,a=(a*a)%mod)if(b&)ret=(ret*a)%mod;
  20. return ret;
  21. }
  22. int upt(int x){while(x>=mod)x-=mod; while(x<)x+=mod; return x;}
  23. void ntt(int *a,int tp,int lim)
  24. {
  25. for(int i=;i<lim;i++)
  26. if(i<rev[i])swap(a[i],a[rev[i]]);
  27. for(int mid=;mid<lim;mid<<=)
  28. {
  29. int p=mod-,len=(mid<<),wn=pw(,tp==?p/len:p-p/len);
  30. for(int j=;j<lim;j+=len)
  31. for(int k=,w=;k<mid;k++,w=(ll)w*wn%mod)
  32. {
  33. int x=a[j+k],y=(ll)w*a[j+mid+k]%mod;
  34. a[j+k]=upt(x+y); a[j+mid+k]=upt(x-y);
  35. }
  36. }
  37. if(tp==)return; int inv=pw(lim,mod-);
  38. for(int i=;i<lim;i++)a[i]=(ll)a[i]*inv%mod;
  39. }
  40. void inv(int *a,int *b,int n)
  41. {
  42. if(n==){b[]=pw(a[],mod-); return;}
  43. inv(a,b,(n+)>>);
  44. int lim=,l=;
  45. while(lim<n+n)lim<<=,l++;
  46. for(int i=;i<lim;i++)rev[i]=((rev[i>>]>>)|((i&)<<(l-)));
  47. for(int i=;i<n;i++)c[i]=a[i];
  48. for(int i=n;i<lim;i++)c[i]=;
  49. ntt(c,,lim); ntt(b,,lim);
  50. for(int i=;i<lim;i++)b[i]=((ll)-(ll)c[i]*b[i])%mod*b[i]%mod;
  51. ntt(b,-,lim);
  52. for(int i=n;i<lim;i++)b[i]=;
  53. }
  54. int main()
  55. {
  56. n=rd(); f[]=; g[]=;
  57. for(int i=;i<n;i++)g[i]=-rd();
  58. inv(g,f,n);
  59. for(int i=;i<n;i++)printf("%d ",f[i]); puts("");
  60. return ;
  61. }

洛谷 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. 【Selenium + Python】路径报错之OSError: [Errno 22] Invalid argument: './t/report/2018-03-23_11:03:12_report.html'

    现象: 此问题真的是太痛苦了,查了好多资料是说路径的问题,结果还是报错,后来一点点的排查才发现原来是!!!!!! 废话不多说上原来代码: if __name__ == '__main__': star ...

  2. OpenCV 入门示例之五:一个复杂点的变换

    前言 前文介绍了一个简单的变换.需要注意的是,很多时候,输出和输入图像的格式是不同的( 大小,深度,通道 ).在本文将展示的程序中,对图像进行了缩放( 使用cvPyrDown 函数 ),这种情况下需要 ...

  3. 目标检测之hog(梯度方向直方图)---hog简介0

    梯度直方图特征(HOG) 是一种对图像局部重叠区域的密集型描述符, 它通过计算局部区域的梯度方向直方图来构成特征.Hog特征结合SVM分类器已经被广泛应用于图像识别中,尤其在行人检测中获得了极大的成功 ...

  4. js jquery 插件

    $(function(){ (function($, document, undefiend){ $.fn.pagination = function(options){ var $this = $( ...

  5. Jmeter文章索引贴

    一.基础部分: 使用Jmeter进行http接口测试 Jmeter之Http Cookie Manager Jmeter之HTTP Request Defaults Jmeter之逻辑控制器(Logi ...

  6. 【BZOJ1604】[Usaco2008 Open]Cow Neighborhoods 奶牛的邻居 Treap+并查集

    [BZOJ1604][Usaco2008 Open]Cow Neighborhoods 奶牛的邻居 Description 了解奶牛们的人都知道,奶牛喜欢成群结队.观察约翰的N(1≤N≤100000) ...

  7. EasyPlayerPro windows播放器在播放RTMP视频显示重复异常问题解决

    问题来源 2017.12.18 今日有杭州某教育领域客户反馈EasyPlayerPro在播放一个rtmp源时,画面显示异常的问题.截图如下: 问题复现 一番思考, 将显示格式改为D3D显示, 正常, ...

  8. 流畅python学习笔记第十八章:使用asyncio包处理并发(一)

    首先是线程与协程的对比.在文中作者通过一个实例分别采用线程实现和asynchio包实现来比较两者的差别.在多线程的样例中,会用到join的方法,下面来介绍下join方法的使用. 知识点一:当一个进程启 ...

  9. 爬虫-Selenium -抱错ElementNotVisibleException: Message: element not visible

    1.当使用Selenium IDE 完成了脚本的录制和回放通过后,想要将脚本转换为其他语言如java.Python等,首次使用时打开Options->Format发现没有可以转换的语言,如下: ...

  10. 用JavaScript判断一个对象是否数组?

    Q:如何判断一个对象是否为数组? A1:判断对象的constructor是否指向Array, 接着判断对应的特殊属性,如length,splice之类.这个很容易冒充. A2:使用instanceof ...