多项式乘法运算终极版

article/2025/8/15 4:16:55

在上一篇文章中 http://blog.csdn.net/acdreamers/article/details/39005227 介绍了用快速傅里叶变

换来求多项式的乘法。可以发现它是利用了单位复根的特殊性质,大大减少了运算,但是这种做法是对复数系数的矩阵

加以处理,每个复数系数的实部和虚部是一个正弦及余弦函数,因此大部分系数都是浮点数,我们必须做复数及浮点数

的计算,计算量会比较大,而且浮点数的计算可能会导致误差增大。

 

今天,我将来介绍另一种计算多项式乘法的算法,叫做快速数论变换(NTT),在离散正交变换的理论中,已经证明在

复数域内,具有循环卷积特性的唯一变换是DFT,所以在复数域中不存在具有循环卷积性质的更简单的离散正交变换。

因此提出了以数论为基础的具有循环卷积性质的快速数论变换

 

回忆复数向量,其离散傅里叶变换公式如下

 

  

 

离散傅里叶逆变换公式为

 

   

 

今天的快速数论变换(NTT)是在上进行的,在快速傅里叶变换(FFT)中,通过次单位复根来运算的,即满

,而对于快速数论变换来说,则是可以将看成是的等价,这里是模素数

的原根(由于是素数,那么原根一定存在)。即

 

       

 

所以综上,我们得到数论变换的公式如下

 

   

 

数论变换的逆变换公式为

 

    

 

这样就把复数对应到一个整数,之后一切都是在系统内考虑。

 

上述数论变换(NTT)公式中,要求是素数且必须是的因子。由于经常是2的方幂,所以可以构造形

的素数。通常来说可以选择费马素数,这样的变换叫做费马数数论变换

 

这里我们选择,这样得到模的原根值为

 

另外附上一篇好文章:从多项式乘法到快速傅里叶变换

 

题目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1028

 

分析:题目意思就是大数相乘,此处用快速数论变换(NTT)实现。

 

代码:

#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
typedef long long LL;
const int N = 1 << 18;
const int P = (479 << 21) + 1;
const int G = 3;
const int NUM = 20;
LL  wn[NUM];
LL  a[N], b[N];
char A[N], B[N];
LL quick_mod(LL a, LL b, LL m)
{
LL ans = 1;
a %= m;
while(b)
{
if(b & 1)
{
ans = ans * a % m;
b--;
}
b >>= 1;
a = a * a % m;
}
return ans;
}
void GetWn()
{
for(int i = 0; i < NUM; i++)
{
int t = 1 << i;
wn[i] = quick_mod(G, (P - 1) / t, P);
}
}
void Prepare(char A[], char B[], LL a[], LL b[], int &len)
{
len = 1;
int L1 = strlen(A);
int L2 = strlen(B);
while(len <= 2 * L1 || len <= 2 * L2) len <<= 1;
for(int i = 0; i < len; i++)
{
if(i < L1) a[i] = A[L1 - i - 1] - '0';
else a[i] = 0;
if(i < L2) b[i] = B[L2 - i - 1] - '0';
else b[i] = 0;
}
}
void Rader(LL a[], int len)
{
int j = len >> 1;
for(int i = 1; i < len - 1; i++)
{
if(i < j) swap(a[i], a[j]);
int k = len >> 1;
while(j >= k)
{
j -= k;
k >>= 1;
}
if(j < k) j += k;
}
}
void NTT(LL a[], int len, int on)
{
Rader(a, len);
int id = 0;
for(int h = 2; h <= len; h <<= 1)
{
id++;
for(int j = 0; j < len; j += h)
{
LL w = 1;
for(int k = j; k < j + h / 2; k++)
{
LL u = a[k] % P;
LL t = w * a[k + h / 2] % P;
a[k] = (u + t) % P;
a[k + h / 2] = (u - t + P) % P;
w = w * wn[id] % P;
}
}
}
if(on == -1)
{
for(int i = 1; i < len / 2; i++)
swap(a[i], a[len - i]);
LL inv = quick_mod(len, P - 2, P);
for(int i = 0; i < len; i++)
a[i] = a[i] * inv % P;
}
}
void Conv(LL a[], LL b[], int n)
{
NTT(a, n, 1);
NTT(b, n, 1);
for(int i = 0; i < n; i++)
a[i] = a[i] * b[i] % P;
NTT(a, n, -1);
}
void Transfer(LL a[], int n)
{
int t = 0;
for(int i = 0; i < n; i++)
{
a[i] += t;
if(a[i] > 9)
{
t = a[i] / 10;
a[i] %= 10;
}
else t = 0;
}
}
void Print(LL a[], int n)
{
bool flag = 1;
for(int i = n - 1; i >= 0; i--)
{
if(a[i] != 0 && flag)
{
//使用putchar()速度快很多
putchar(a[i] + '0');
flag = 0;
}
else if(!flag)
putchar(a[i] + '0');
}
puts("");
}
int main()
{
GetWn();
while(scanf("%s %s", A, B) != EOF)
{
int len;
Prepare(A, B, a, b, len);
Conv(a, b, len);
Transfer(a, len);
Print(a, len);
}
return 0;
}


 


http://chatgpt.dhexx.cn/article/t7Gq8iBi.shtml

相关文章

多项式乘法(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…

分库分表和 NewSQL 到底怎么选?

文章来源&#xff1a;【公众号&#xff1a;CoderW】 目录 背景分表分库分库分表的成本NewSQLNewSQL 平滑接入方案NewSQL 真的有那么好吗&#xff1f;NewSQL 的应用分库分表和 NewSQL 到底怎么选&#xff1f; 背景 曾几何时&#xff0c;“并发高就分库&#xff0c;数据大就分表”…

软考初级-信息处理技术员

22年下半年也是顺利通过了软考初级-信息处理技术员&#xff0c;明年再报一次软设&#xff0c;今年上半年软设下午题没过&#xff0c;总结还是代码敲的少&#xff0c;想的太多hh&#xff0c;下面来看看我总结的上午题考点&#xff0c;非常感谢我好友老郑教我指点了我excel的函数…

学术交流 | InForSec 2023年网络空间安全国际学术研究成果分享及青年学者论坛

隐私计算研习社 InForSec定于2023年4月8日&#xff5e;9日&#xff08;周六、日&#xff09;在南方科技大学举办“InForSec 2023年网络空间安全国际学术研究成果分享及青年学者论坛”。本次学术活动将邀请在网络空间安全顶级会议上发表论文的研究者分享他们的最新研究成果&…

用matlab绘制光滑曲线(plot画出的为折线)

x[0 0.1 0.16 0.27 0.41 0.48 0.59 0.8] y[5 9 70 118 100 17 0 5]; 那么用plot画出的函数为折线&#xff0c;如下图&#xff1a; 要想把那个折点平滑掉。像论文中那样&#xff0c;具体采用样条函数&#xff1a;下面是样条函数的定义&#xff1a; spline function 一类分段&…

matlab plot画曲线/直线/椭圆

本博文源于matlab基础&#xff0c;每个图像一个案例引入&#xff0c;大家简单看&#xff0c;直接照猫画虎去套用就行了。 画直线 例子&#xff1a;画y2*x3 范围为[1,10] 代码&#xff1a; >> x1:10; >> y2*x3; >> plot(y) >> 画曲线 在区间[-Π,Π…