热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

51nod1172PartialSumsV2任意模数FFT

题意给出一个数组A,经过一次处理,生成一个数组S,数组S中的每个值相当于数组A的累加,比如:A{1356}

题意

给出一个数组A,经过一次处理,生成一个数组S,数组S中的每个值相当于数组A的累加,比如:A = {1 3 5 6} => S = {1 4 9 15}。如果对生成的数组S再进行一次累加操作,{1 4 9 15} => {1 5 14 29},现在给出数组A,问进行K次操作后的结果。(输出结果 Mod 10^9 + 7)
2 <&#61; n <&#61; 50000, 0 <&#61; k <&#61; 10^9, 0 <&#61; a[i] <&#61; 10^9


分析

首先有个结论就是ans[n]&#61;ni&#61;0Cii&#43;k1a[ni]ans[n]&#61;∑i&#61;0nCi&#43;k−1i∗a[n−i]
这条式子是怎么来的呢&#xff1f;我的理解就是&#xff0c;把每一次前缀和后的数组放在一起&#xff0c;初始数组在第0行&#xff0c;前缀和放在第一行&#xff0c;如此类推。那么a[i]对a[n]贡献的系数就相当于每次可以从(x,y)走到(x&#43;1,y&#43;l)&#xff08;l>&#61;0&#xff09;&#xff0c;从(0,i)走到(k,n)的不同方案数。根据隔板法不难得到系数就是Cnini&#43;k1Cn−i&#43;k−1n−i
上面的式子是一个卷积的形式&#xff0c;可以用FFT来优化。但注意到这里的模数并不是NTT模数&#xff0c;那么就要用到任意模数FFT。
具体来讲就是取M&#61;PM&#61;P&#xff0c;设f(x)&#61;k(x)M&#43;r(x)f(x)&#61;k(x)∗M&#43;r(x)&#xff0c;那么有
f1(x)f2(x)&#61;(k1(x)M&#43;r1(x))(k2(x)M&#43;r2(x))f1(x)∗f2(x)&#61;(k1(x)∗M&#43;r1(x))∗(k2(x)∗M&#43;r2(x))
&#61;M2k1(x)k2(x)&#43;M(k1(x)r2(x)&#43;k2(x)r1(x))&#43;r1(x)r2(x)&#61;M2∗k1(x)∗k2(x)&#43;M∗(k1(x)∗r2(x)&#43;k2(x)∗r1(x))&#43;r1(x)∗r2(x)
总共需要做7次FFT且卷积后元素的数量级为O(nP)&#xff0c;可以用long double来进行FFT而不是高精度。
一开始打完后被卡了精度&#xff0c;后面把pi从define变成const就过了。。。
第一次手打复数类型&#xff0c;发现比自带的要快将近一倍。。。


代码

#include
#include
#include
#include
#include
#includeusing namespace std;typedef long long LL;const int MOD&#61;1000000007;
const int N&#61;50005;
const long double pi&#61;acos((long double)-1);struct com
{long double x,y;com operator &#43; (const com &d) {return (com){x&#43;d.x,y&#43;d.y};}com operator - (const com &d) {return (com){x-d.x,y-d.y};}com operator * (const com &d) {return (com){x*d.x-y*d.y,x*d.y&#43;d.x*y};}com operator / (const long double &d) {return (com){x/d,y/d};}
};int n,M,ny[N],c[N],a[N],k,L,rev[N*4];
com s1[N*4],s2[N*4],s3[N*4],k1[N*4],r1[N*4],k2[N*4],r2[N*4];int read()
{int x&#61;0,f&#61;1;char ch&#61;getchar();while (ch<&#39;0&#39;||ch>&#39;9&#39;){if(ch&#61;&#61;&#39;-&#39;)f&#61;-1;ch&#61;getchar();}while (ch>&#61;&#39;0&#39;&&ch<&#61;&#39;9&#39;){x&#61;x*10&#43;ch-&#39;0&#39;;ch&#61;getchar();}return x*f;
}void init()
{n&#61;read();k&#61;read();for (int i&#61;0;i0]&#61;ny[1]&#61;c[0]&#61;1;c[1]&#61;k;for (int i&#61;2;i1]*(k&#43;i-1)%MOD;for (int i&#61;2;i1]%MOD,c[i]&#61;(LL)c[i]*ny[i]%MOD;
}void fft(com *a,int f)
{for (int i&#61;0;iif (ifor (int i&#61;1;i1){com wn&#61;(com){cos(pi/i),f*sin(pi/i)};for (int j&#61;0;j1)){com w&#61;(com){1,0};for (int k&#61;0;kif (f&#61;&#61;-1) for (int i&#61;0;i}int main()
{init();M&#61;sqrt(MOD);int lg&#61;0;for (L&#61;1;L<&#61;n*2;L<<&#61;1,lg&#43;&#43;);for (int i&#61;0;i>1]>>1)|((i&1)<<(lg-1));for (int i&#61;0;i0.0},r1[i]&#61;(com){a[i]%M,0.0},k2[i]&#61;(com){c[i]/M,0.0},r2[i]&#61;(com){c[i]%M,0.0};fft(k1,1);fft(r1,1);fft(k2,1);fft(r2,1);for (int i&#61;0;i1);fft(s2,-1);fft(s3,-1);for (int i&#61;0;iint x1&#61;(LL)(s1[i].x&#43;0.5)%MOD*M*M%MOD,x2&#61;(LL)(s2[i].x&#43;0.5)%MOD*M%MOD,x3&#61;(LL)(s3[i].x&#43;0.5)%MOD;int ans&#61;x1&#43;x2;ans-&#61;ans>&#61;MOD?MOD:0;ans&#43;&#61;x3;ans-&#61;ans>&#61;MOD?MOD:0;printf("%d\n",ans);}return 0;
}

推荐阅读
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文介绍了一个题目的解法,通过二分答案来解决问题,但困难在于如何进行检查。文章提供了一种逃逸方式,通过移动最慢的宿管来锁门时跑到更居中的位置,从而使所有合格的寝室都居中。文章还提到可以分开判断两边的情况,并使用前缀和的方式来求出在任意时刻能够到达宿管即将锁门的寝室的人数。最后,文章提到可以改成O(n)的直接枚举来解决问题。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 本文讨论了一个数列求和问题,该数列按照一定规律生成。通过观察数列的规律,我们可以得出求解该问题的算法。具体算法为计算前n项i*f[i]的和,其中f[i]表示数列中有i个数字。根据参考的思路,我们可以将算法的时间复杂度控制在O(n),即计算到5e5即可满足1e9的要求。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • IhaveconfiguredanactionforaremotenotificationwhenitarrivestomyiOsapp.Iwanttwodiff ... [详细]
  • 本文介绍了解决二叉树层序创建问题的方法。通过使用队列结构体和二叉树结构体,实现了入队和出队操作,并提供了判断队列是否为空的函数。详细介绍了解决该问题的步骤和流程。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • 本文介绍了UVALive6575题目Odd and Even Zeroes的解法,使用了数位dp和找规律的方法。阶乘的定义和性质被介绍,并给出了一些例子。其中,部分阶乘的尾零个数为奇数,部分为偶数。 ... [详细]
  • 3.223.28周学习总结中的贪心作业收获及困惑
    本文是对3.223.28周学习总结中的贪心作业进行总结,作者在解题过程中参考了他人的代码,但前提是要先理解题目并有解题思路。作者分享了自己在贪心作业中的收获,同时提到了一道让他困惑的题目,即input details部分引发的疑惑。 ... [详细]
  • 开发笔记:实验7的文件读写操作
    本文介绍了使用C++的ofstream和ifstream类进行文件读写操作的方法,包括创建文件、写入文件和读取文件的过程。同时还介绍了如何判断文件是否成功打开和关闭文件的方法。通过本文的学习,读者可以了解如何在C++中进行文件读写操作。 ... [详细]
  • Go语言实现堆排序的详细教程
    本文主要介绍了Go语言实现堆排序的详细教程,包括大根堆的定义和完全二叉树的概念。通过图解和算法描述,详细介绍了堆排序的实现过程。堆排序是一种效率很高的排序算法,时间复杂度为O(nlgn)。阅读本文大约需要15分钟。 ... [详细]
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
author-avatar
手机用户2502887831
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有