多项式乘法入门

article/2025/8/15 7:52:13

多项式乘法入门

By SemiWaker

这是一篇蒟蒻对FFT、DFT、CZT、NTT的弱鸡理解

多项式

a0x+a1x1+a2x2+an1xn1

上面的这个形式叫做多项式。
系数: a0..n1
项: aixi
界:n
为了方便我们系数序列就可以表示多项式。

线性卷积

A×B=i=02n2(j=0iAjBij)xi

简单来说,就是把两个多项式直接乘起来。
第i项的构成如下:
任取两个项 Ajxj Bkxk ,如果 j+k=i ,那么得到 AjBkxi
将所有 j+k=i 的项系数两两相乘加起来即可。

循环卷积

A×B=i=0n1(j,kAjBk[j+ki(modn)])xi

比较难理解。
其实就是把多项式的-1项设为n-1项,-2项设为n-2项……
然后,线性卷积为了防止出现-1项,设定了j<=i,现在我们把它去掉。
A×B=i=0n1(j=0n1AjBij)xi

线性卷积和循环卷积关系

我们用比较形象地方式说明。
举个例子

(1+2x+3x2+4x3)×(5+6x+7x2+8x4)

(1,2,3,4)×(5,6,7,8)
线性卷积:
线性卷积
循环卷积
循环卷积
如果把 (5,6,7,8) 复制展开
循环卷积展开
然后我们观察,设线性卷积的结果为 C0...6 ,循环卷积的结果为 D0..3
则有:
D0=C0+C4
D1=C1+C5
D2=C2+C6
D3=C3
也就是说,把线性卷积重叠在一起,就得到了循环卷积。

多项式点值表示

我们把N个数 x0..n1 带入x,可以得到多项式的N个值 A(x0..n1)
将每一个数和对应的值当成一个点 (xi,A(xi)) ,这N个点叫做多项式的点值表示。
为什么点值表示可以代表多项式呢?
因为我们可以反过来用点值表示求出多项式。
待定系数+解方程就可以了。

多项式插值

就是把点值表示转换成系数表示的一个过程。

DFT

离散傅里叶变换
考虑怎样快速求多项式卷积。
按照定义去写 O(n2) ,显然不优。

我们可以考虑点值表示。
两个多项式如果取值用的是同样的数 x0..n1 ,那么得到的值直接乘起来就可以得到卷积之后的多项式的点值表示。

但是如果按照定义一个一个数带入求多项式的值,还是 O(n2) 的,没有优化。

我们考虑带入特殊的数去求点值表示。

DFT就是这样一个过程:将一个多项式转化为用n次单位根表示的点值表示。

FFT是实现DFT的算法。

单位根

简单来说 xn=1 的复数解。
n次单位根有n个复数解,设为 ωkn ,其中k=0…n-1。
ωkn=e2kπIn
用欧拉公式展开:
exI=cos(x)+sin(x)I
得到
(ωkn)n=cos(2kπ)+sin(2kπ)I=1

画在复数平面上,刚好是把单位元n等分的n个点。

有一些有趣的性质
ωkn=ωk(modn)n
由三角函数周期性可证。
ωn2n=1
显然。
ωnn=1
显然。
ωkn=ωk2n2
显然。
(ωkn)2=(ωk+n2n)2
把定义带入可证。

FFT的实现

快速傅里叶变换 Cooley-Tukey算法
考虑把 ω0...n1n 一起带入求值。

Ak=j=0n1aj(ωkn)j

可以分治为两部分
Ak=j=0n12a2j(ωkn)2j+(ωkn)j=0n12a2j+1(ωkn)2j

两半的长度都为 n2

(ωkn)2j=(ωk+n/2n)2j=ωkjn2
所以而 ωkjn2 只有 n2 个取值,而且每个出现两次。

这样就通过分治减小了规模。

现在变成了对两个多项式 (a0,a2,a4...) (a1,a3,a5...) 求带入 ω0..n21n2

分治完了之后,我们要求回原来的多项式。
设分治的结果为 B0..n21 C0..n21
Ak=Bk+ωknCk
但是注意此时k只有 n2
所以 Ak+n2=Bk+ωk+n2nCk
ωk+n2n=ωkn
所以 Ak+n2=BkωknCk

用一个简单的图来记:
蝴蝶变换
设当前分治长度为L,则
Ak=Ak+ωknAk+L2
Ak+L2=AkωknAk+L2
注意变量自我迭代时,要开临时变量
这两个位置刚好交错计算,形状类似蝴蝶,所以叫做蝴蝶变换。

边界:
n=1时, ω11=1 ,所以直接把 ak 放进去就好了。

程序怎么实现呢?
直接分治是可以的,但是有更好的方法。
我们考虑分治时的分类方法:
每一层按照奇偶数。
如果我们保持编号不变,那么就变成:第i行按照从低到高第i位分。
由于是从低到高,所以最后的排列为:每一个数的位置,为编号二进制倒序后位置。
举例:有8个数,编号0~7。
分治过程:
000 001 010 011 100 101 110 111
000 010 100 110|001 011 101 111
000 100|010 110|001 101|011 111
000|100|010|110|001|101|011|111

把最后一行的二进制倒过来:
000 001 010 011 100 101 110 111
刚好是从0~7。

设Reverse(x)为x二进制倒序后的数
一开始我们可以将ai放到Reverse(i)的位置。

然后设当前层分治长度为L。
每L个一起处理,进行蝴蝶变换即可。

进一步优化,注意蝴蝶变换中 ωkn 的k取值为0~L/2
为了尽量减少对 ωkn 的计算次数,我们可以先枚举0~L/2,计算 ωkn ,然后枚举每一个分治块的相应位置进行蝴蝶变换。

IDFT

逆离散傅里叶变换
求出点值表示,再相乘之后,我们要进行插值操作。
通过对DFT求逆矩阵,我们直接给出以下结论:
将点值表示 (A0,A1...An) 转换为系数表示 (a0,a1...an) ,只需要求出:

ai=n1i=0Ai(ωkn)in

换句话说,我们要把DFT中的每一个 ωkn 换成 ωkn ,然后除以n即可。

代码

void FFT(Complex *A,int n,int sgn)
{for (int i=1;i<n-1;++i){int j=0;for (int t=1,k=i;t<n;t<<=1,j=((j<<1)|(k&1)),k>>=1);if (j>i) swap(A[i],A[j]);}for (int L=2;L<=n;L<<=1){int L1=L>>1;for (int i=0;i<L1;++i){Complex w=Complex(cos(sgn*PI*i/L1),sin(sgn*PI*i/L1));for (int j=i;j<n;j+=L){int k=j+L1;Complex u=A[j],v=w*A[k];A[j]=u+v;A[k]=u-v;}}}if (sgn==-1) for (int i=0;i<n;++i) A[i]=A[i]/Complex(n,0.0);
}

至于是用exp还是直接两个三角函数,一个exp应该是快些,但是只能用STL的complex。如果要手写complex就只能两个三角函数。手写会快些。
注意:因为要对2分治,所以要强行把项数补到 2n ,后面的项系数为0。如果是两个长度为n的多项式相乘,那么至少要开4n的空间。

循环卷积和线性卷积对于DFT的区别

线性卷积卷得到项数是2n-1,而循环卷积得到的项数是n。
那么我们在求点值表示的时候,线性卷积就带入2n-1个点,循环卷积就带入n个点,再相应的IDFT出来的结果就是所求的结果。

CZT

Z-变换
在用FFT的过程中,我们要强行把多项式补到 2n 项。那么,FFT出来的点值表示,实际上和原来的点值表示已经不一样了。(因为n变了
在求线性卷积的时候,补足 2n 项没有什么问题。但是如果要求循环卷积,补足 2n 位就会产生很大的问题。(定义决定的

求循环卷积时,我们要保证项数不变,DFT出来的点值表示才能表示原来的循环卷积。

怎样保证项数不变呢?

考虑原来的公式

Ak=j=0n1aj(ωkn)j

Ak=j=0n1aje2πjknI

考虑我们把jk变换一下。
其实是更加复杂了
jk=j2+k2(jk)22
然后带入

Ak=j=0n1ajeπ(j2+k2(jk)2)nI

稍微变化下
Ak=eπk2nIj=0n1ajeπj2nIeπ(kj)2nI

Bj=ajeπj2nI
Cj=eπj2nI
那么
Ak=eπk2nIj=0n1ajBjCkj

右边是一个线性卷积,所以我们可以用一次FFT来完成一次DFT

注意,k-j会小于0!
怎么解决这个问题呢?
我们把C右移n位。那么此时
Cj=eπ(jn)2nI
由于平方的存在,所以不会有问题。

此时C的长度变为2n。
卷积完之后总长3n。
我们需要考虑哪些部分是有用的。
哪些部分可以保证k-j>=0呢?
An..2n1
那么,最后的答案应该是: Ak=eπk2nIAk+n
注意IDFT时同样要除以n。

这样我们就完成了项数不变的DFT。实际上,应该叫做CZT。

NTT

数论变换
考虑这个问题:乘起来后系数要模怎么办?

由于单位根是个复数,不能够模。
所以我们要找一个可以代替的东西。

考虑我们用了哪些性质,简单来说, ωkn 是一个n阶的循环群。

设我们现在模的质数为 P=2tQ+1
考虑模P意义下的原根g。

由于 g0...P1 两两不同, gP=g g2t1Q=1 ,所以是一个 2tQ 阶的循环群。

进一步,我们可以得到 (gQ)0..P1 2t 阶的循环群。
n=2t 即可。

然后我们对应着 ωkn 的定义,定义 Gkn=g2tkQn
显然 Gkn 有n个,而且满足 Gkn=Gk2n2 ,也满足 Gk+n2n=Gkn

预处理出 gkQ 代替单位根即可。

如果我们要模m,但是m不是 2tQ+1 形式的质数怎么办?
暴力法:在模m的情况下,每一个系数最大为 m-1,两个乘起来最多 (m1)2 ,n个加起来最多 n(m1)2
我们只要凑一个超过 n(m1)2 的模数就好了。这样在NTT的过程中,就不会让系数发生变化。然后再去一项一项模。

怎么凑呢?我们用几个小的 2tQ+1 形式的质数去做NTT,然后用中国剩余定理合并起来就好了。


http://chatgpt.dhexx.cn/article/4hgJK7ZB.shtml

相关文章

一元多项式的乘法与加法运算

题目要求 设计函数分别求两个一元多项式的乘积与和。 输入格式: 输入分2行&#xff0c;每行分别先给出多项式非零项的个数&#xff0c;再以指数递降方式输入一个多项式非零项系数和指数&#xff08;绝对值均为不超过1000的整数&#xff09;。数字间以空格分隔。 输出格式: 输…

多项式乘法运算初级版

快速傅里叶变换在信息学竞赛中主要用于求卷积&#xff0c;或者说多项式乘法。我们知道&#xff0c;多项式乘法的普通算法时间复杂度 是&#xff0c;通过快速傅里叶变换可以使时间降为&#xff0c;那么接下来会详细介绍快速傅里叶变换的原理。 首先来介绍多项式的两种表示方法&…

FFT与多项式乘法

网上关于FFT在信号处理中应用的文章并不少&#xff0c;这里尽量少说废话&#xff0c;直接说如何用FFT实现多项式乘法。 多项式乘法&#xff0c;通常是用系数乘积的方式完成&#xff0c;这样的时间复杂度是O(n^2) n为多项式项数。系数乘法可以满足大多数的乘法需求&#xff0c;然…

多项式乘法

实验题目&#xff1a;多项式乘法问题 实验内容与要求 一元稀疏多项式简单计算器的基本功能是&#xff1a; &#xff08;1)输入并建立多项式。&#xff1b; &#xff08;2&#xff09;输出多项式&#xff0c;输出形式为整数序列&#xff1a;n,c1,e1,c2,e2,…,cn,en,其中n是多项…

多项式乘法运算终极版

在上一篇文章中 http://blog.csdn.net/acdreamers/article/details/39005227 介绍了用快速傅里叶变 换来求多项式的乘法。可以发现它是利用了单位复根的特殊性质&#xff0c;大大减少了运算&#xff0c;但是这种做法是对复数系数的矩阵 加以处理&#xff0c;每个复数系数的实…

多项式乘法(FFT)

1 前言 作为一名OI选手&#xff0c;至今未写过fft相关的博客&#xff0c;真是一大遗憾&#xff0c;这也导致我并没有真正推过fft的所有式子 这一篇fft的博客我将详细介绍多项式乘法&#xff0c;易于理解&#xff0c;主要是为了等我啥时候忘了回来看&#xff0c;当然&#xff0…

分治算法-03多项式乘法问题

多项式乘法 简介 多项式的运算表示是一个很常见的算法问题。 问题描述 给予两个多项式A(x)与B(x)&#xff0c;得出C(x)A(x)B(x)。例如&#xff0c;A(x)32x3x24x3&#xff0c;B(x)2x2&#xff0c;C(x)64x9x210x33x44x^5。 问题分析 一般情况下&#xff0c;使用系数表示多项式&a…

【数据结构】——多项式乘法

题目要求 从字符文件输入两个多项式的非零系数及对应的指数&#xff0c;建立多项式的链式存储结构&#xff0c;计算这两个多项式的乘积&#xff0c;输出乘积多项式的全部非零系数及对应的指数到另一字符文件中。 算法原理 两个多项式的乘法&#xff0c;可以借助两个多项式的…

多项式乘法(FFT)详解

本文只探讨多项式乘法(FFT)在信息学中的应用 如有错误或不明欢迎指出或提问&#xff0c;在此不胜感激 多项式 1. 系数表示法 一般应用最广泛的表示方式 用A(x)表示一个x-1次多项式&#xff0c;a[i]为 xi x i 的系数&#xff0c;则A(x) ∑n−10 ∑ 0 n − 1 a[i] * xi x i…

2.2 多项式乘法与加法运算(线性结构,C)

多项式乘法与加法运算 设计函数分别求两个一元多项式的乘积与和题意理解题意理解和积 求解思路多项式表示两种表示方式在事先已经知道具体多少项的时候&#xff0c;本题较好的实现方法&#xff1a;动态数组链表表示多项式的方法 程序框架如何读入多项式读入多项式的完整程序 加…

多项式乘法问题

多项式乘法问题 实验目的&#xff1a;设计一个一元稀疏多项式简单计算器。 实验内容与要求&#xff1a; 一元稀疏多项式简单计算器的基本功能是&#xff1a; &#xff08;1&#xff09;输入并建立多项式&#xff1b; &#xff08;2&#xff09;输出多项式&#xff0c;序列…

网络协议之视频直播核心技术讲解

网络视频直播存在已有很长一段时间&#xff0c;随着移动上下行带宽提升及资费的下调&#xff0c;视频直播被赋予了更多娱乐和社交的属性&#xff0c;人们享受随时随地进行直播和观看&#xff0c;直播的打开时间和延迟变成了影响产品功能发展重要指标。 那么&#xff0c;问题来了…

直播软件搭建技术原理:CDN 与直播

直播软件搭建技术原理&#xff1a;CDN 与直播 很多直播都是基于 CDN 来实现的。而通过声网的服务&#xff0c;或基于声网SDK与 CDN 结合&#xff0c;还可以实现在直播中的连麦互动、白板同步等强调实时性的场景。本文源自社区投稿&#xff0c;介绍了该场景下的一些基础知识。如…

暑期实习+秋招面经合集(更新ing)

大纲 开篇 自我介绍 &#xff1a;面试官你好&#xff0c;我叫林飞武&#xff0c;是一名通信工程大三学生&#xff0c;对计算机专业有着浓厚兴趣并且未来有志于在互联网的测试领域有深入发展。全套学习了计算机专业的专业课&#xff0c;计算机网络&#xff0c;操作系统等&#…

DNSPod十问王征:为什么你的网站无人问津?

&#x1f4e2; DNSPod十八周年庆将至&#xff0c;下期十问交给你来提问——《你&#xff0c;十问DNSPod》&#xff01;评论区留下你想问DNSPod团队的问题&#xff0c;一旦提问被选中&#xff0c;将得到十八周年纪念T恤&#xff01;详情请移步至DNSPod公众号十八周年庆推送。 广…

阿里云ACP认证考试笔记

课件&#xff1a;https://gitee.com/HanFerm/technical-documentation/tree/master/阿里云acp教材 本文档为公开内容 一、ACP是干嘛的 内容范围&#xff1a; 历史 二、阿里云综述 技术架构 优势 三、弹性计算 ECS ECS的组成与功能 ECS是由多个并列又相互关联的产品概念组成…

在互联网上,没有人知道你是一条狗?

1993 年&#xff0c;《纽约客》&#xff08;The New Yorker&#xff09;杂志刊登一则由彼得施泰纳&#xff08;Peter Steiner&#xff09;创作的漫画&#xff1a;标题是【On the Internet, nobody knows you’re a dog.】 这则漫画中有两只狗&#xff1a;一只黑狗站在电脑椅上…

分库分表和NewSQL如何选择?分库分表真的适合你的系统吗?

曾几何时&#xff0c;“并发高就分库&#xff0c;数据大就分表”已经成了处理 MySQL 数据增长问题的圣经。 面试官喜欢问&#xff0c;博主喜欢写&#xff0c;候选人也喜欢背&#xff0c;似乎已经形成了一个闭环。 但你有没有思考过&#xff0c;分库分表真的适合你的系统吗&am…

分库分表不一定适合你的系统,聊聊分库分表和NewSQL如何选择

曾几何时&#xff0c;“并发高就分库&#xff0c;数据大就分表”已经成了处理 MySQL 数据增长问题的圣经。 面试官喜欢问&#xff0c;博主喜欢写&#xff0c;候选人也喜欢背&#xff0c;似乎已经形成了一个闭环。 但你有没有思考过&#xff0c;分库分表真的适合你的系统吗&am…

分库分表真的适合你的系统吗?聊聊分库分表和NewSQL如何选择

曾几何时&#xff0c;“并发高就分库&#xff0c;数据大就分表”已经成了处理 MySQL 数据增长问题的圣经。 面试官喜欢问&#xff0c;博主喜欢写&#xff0c;候选人也喜欢背&#xff0c;似乎已经形成了一个闭环。 但你有没有思考过&#xff0c;分库分表真的适合你的系统吗&am…