刚学完FFT,干脆把NTT也学了算了

(一)预备知识

关于原根,这里说得蛮详细的百度百科

为什么使用原根呢?为什么原根可以替代\(\omega_{n}\)呢?想知道为什么就看here

NTT用到的各种素数,在这里here

(二)重要知识

直接上代码

原题洛谷P1919

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
typedef long long ll;
typedef double dd;
#define For(i,j,k) for (int i=j;i<=k;++i)
#define Forr(i,j,k) for (int i=j;i>=k;--i)
#define Set(a,p) memset(a,p,sizeof(a))
using namespace std; template<typename T>bool chkmax(T& a,T b) {return a<b?a=b,1:0;}
template<typename T>bool chkmin(T& a,T b) {return a>b?a=b,1:0;} const int maxn=200000+100;
const ll modd=998244353;
int n,N,cnt;
int p[maxn];
ll g,a[maxn],b[maxn];
char ss[maxn]; ll quick(ll a,ll b) {
ll s=1;
while (b) {
if (b%2) s=s*a%modd;
a=a*a%modd; b/=2;
}
return s;
} inline void NTT(ll *s,int type) {
For (i,0,N-1)
if (i<p[i]) swap(s[i],s[p[i]]);
for (int mid=1;mid<N;mid<<=1) {
int len=mid<<1;
ll wn=quick(g,type==1?(modd-1)/len:modd-1-(modd-1)/len);
for (int j=0;j<N;j+=len) {
ll w=1;
for (int k=0;k<mid;++k,w=w*wn%modd) {
ll t=w*s[j+mid+k]%modd;
s[j+mid+k]=(s[j+k]-t+modd)%modd;
s[j+k]=(s[j+k]+t)%modd;
}
}
}
if (type==-1) {
ll inv=quick(N,modd-2);
For (i,0,N) s[i]=s[i]*inv%modd;
}
} int main() {
scanf("%d",&n);
scanf("%s",ss);
For (i,0,n-1) a[i]=ss[n-1-i]-'0';
scanf("%s",ss);
For (i,0,n-1) b[i]=ss[n-1-i]-'0';
for (N=1;N<2*n;N<<=1,++cnt) ;
For (i,0,N-1) p[i]=p[i>>1]>>1 | ((i&1)<<(cnt-1));
g=3;
NTT(a,1); NTT(b,1);
For (i,0,N) a[i]=a[i]*b[i]%modd;
NTT(a,-1);
ll x=0;
For (i,0,N) {
a[i]+=x; x=a[i]/10; a[i]%=10;
}
while (!a[N]) N--;
Forr (i,N,0) printf("%lld",a[i]);
return 0;
}

代码要注意,long long 不可乱用!!!

快速数论变换(NTT)的更多相关文章

  1. 【算法】快速数论变换(NTT)初探

    [简介] 快速傅里叶变换(FFT)运用了单位复根的性质减少了运算,但是每个复数系数的实部和虚部是一个余弦和正弦函数,因此系数都是浮点数,而浮点数的运算速度较慢且可能产生误差等精度问题,因此提出了以数论 ...

  2. Algorithm: 多项式乘法 Polynomial Multiplication: 快速傅里叶变换 FFT / 快速数论变换 NTT

    Intro: 本篇博客将会从朴素乘法讲起,经过分治乘法,到达FFT和NTT 旨在能够让读者(也让自己)充分理解其思想 模板题入口:洛谷 P3803 [模板]多项式乘法(FFT) 朴素乘法 约定:两个多 ...

  3. JZYZOJ 2041 快速数论变换 NTT 多项式

    http://172.20.6.3/Problem_Show.asp?id=2041 https://blog.csdn.net/ggn_2015/article/details/68922404 代 ...

  4. [快速数论变换 NTT]

    先粘一个模板.这是求高精度乘法的 #include <bits/stdc++.h> #define maxn 1010 using namespace std; char s[maxn]; ...

  5. 快速数论变换(NTT)小结

    NTT 在FFT中,我们需要用到复数,复数虽然很神奇,但是它也有自己的局限性--需要用double类型计算,精度太低 那有没有什么东西能够代替复数且解决精度问题呢? 这个东西,叫原根 原根 阶 若\( ...

  6. 模板 - 数学 - 多项式 - 快速数论变换/NTT

    Huffman分治的NTT,常数一般.使用的时候把多项式的系数们放进vector里面,然后调用solve就可以得到它们的乘积.注意这里默认最大长度是1e6,可能需要改变. #include<bi ...

  7. 快速数论变换NTT模板

    51nod 1348 乘积之和 #include <cmath> #include <iostream> #include <cstdio> #include &l ...

  8. 从傅里叶变换(FFT)到数论变换(NTT)

    FFT可以用来计算多项式乘法,但是复数的运算中含有大量的浮点数,精度较低.对于只有整数参与运算的多项式,有时,\(\text{NTT(Number-Theoretic Transform)}\)会是更 ...

  9. 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/常用套路【入门】

    原文链接https://www.cnblogs.com/zhouzhendong/p/Fast-Fourier-Transform.html 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/ ...

  10. 「算法笔记」快速数论变换(NTT)

    一.简介 前置知识:多项式乘法与 FFT. FFT 涉及大量 double 类型数据操作和 \(\sin,\cos\) 运算,会产生误差.快速数论变换(Number Theoretic Transfo ...

随机推荐

  1. EWS Managed API 2.0 设置获取邮件自动回复功能

    摘要 最近要在邮件提醒功能中添加,自动回复的功能.在移动端获取用户在outlook上是否开启了自动回复功能,如果用户在outlook上开启了自动回复功能, 获取用户自动回复的内容,如果没有开启,用户可 ...

  2. (译文)The Linux Programming Interface:第1章(历史和标准)

    1 HISTORY AND STANDARDS (译者:鱼时代  校对:fgn) Linux 是UNIX操作系统家族中的一员,在计算机出现以来,UNXI已经有很长的历史了.在这一章中的第一部分将对Un ...

  3. Oracle总结之plsql编程(基础九)

    原创作品,转自请注明出处:https://www.cnblogs.com/sunshine5683/p/10344302.html 接着上次总结,继续今天的总结,今天主要总结plsql中控制语句,如条 ...

  4. Java - equals方法

    java提高篇(十三)-----equals()方法总结 equal和==区别 ==比较对象基于内存引用,两个引用完全相同返回true Java 语言里的 equals方法其实是交给开发者去覆写的,让 ...

  5. Java-函数式编程(一)初识篇

    开发者使用Java8编写复杂的集合处理算法,只需要简单的代码就能在多喝cpu上高效运行,这就是Lambda表达式的初衷. 提示:函数式编程和语言无关,它是一种思想,任何语言都可以实现函数式编程,区别只 ...

  6. 【学习笔记】--- 老男孩学Python,day3 while 循环 运算符 逻辑、赋值运算

    1. 循环. while循环 while 条件: 代码块(循环体) 执行流程: 1. 判断条件是否为真. 如果真. 执行代码块 2. 再次判断条件是否为真...... 3. 当条件为假.执行else ...

  7. python-解释器模式

    源码地址:https://github.com/weilanhanf/PythonDesignPatterns 说明: 解释器模式在面向对象语言实现的编译器中得到了广泛的应用.但是此模式进适用于建大的 ...

  8. python并发编程-线程和锁

    什么是线程 进程:资源分配单位 线程:cpu执行单位(实体),每一个py文件中就是一个进程,一个进程中至少有一个线程 线程的两种创建方式: from multiprocessing import Pr ...

  9. layui 页面加载 阴影 请求页面加载转圈页面

    var layerIndex= layer.load(1,{shade: [0.3, '#000']}); $.post('${pageContext.request.contextPath}/lea ...

  10. git基础使用——TortoiseGit

    一.初识git Git是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目. Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制 ...