模板 NTT 快速数论变换

NTT裸模板,没什么好解释的

这种高深算法其实也没那么必要知道原理

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #define N (1<<17)+10
 5 #define ll long long
 6 using namespace std;
 7
 8 ll inv3,invl;
 9 int r[N];
10 ll A[N],B[N],C[N],mulwn[N],invwn[N];
11 char s1[N],s2[N];
12 const ll p=998244353;
13 ll qpow(ll x,ll y,ll mo){
14     ll ans=1;
15     while(y){
16         if(y&1) ans=(ans*x)%mo;
17         x=(x*x)%mo,y>>=1;
18     }return ans;
19 }
20 void pre(int len,int l)
21 {
22     inv3=qpow(3,p-2,p),invl=qpow(len,p-2,p);
23     for(int i=0;i<len;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
24     for(ll i=1;i<=len;i<<=1) mulwn[i]=qpow(3,(p-1)/i,p);
25     for(ll i=1;i<=len;i<<=1) invwn[i]=qpow(mulwn[i],p-2,p);
26 }
27 void NTT(ll *a,int len,int type)
28 {
29     for(int i=0;i<len;i++)
30         if(i<r[i]) swap(a[i],a[r[i]]);
31     for(int k=2;k<=len;k<<=1)
32     {
33         ll wn=(type>0)?mulwn[k]:invwn[k];
34         int mid=k>>1;
35         for(int i=0;i<len;i+=k)
36         {
37             ll w=1;
38             for(int j=0;j<mid;j++,w=(w*wn)%p)
39             {
40                 ll t=(w*a[i+j+mid])%p;
41                 a[i+j+mid]=(a[i+j]-t+p)%p;
42                 a[i+j]=(a[i+j]+t)%p;
43             }
44         }
45     }
46     if(type==-1)
47         for(int i=0;i<len;i++)
48             a[i]=(a[i]*invl)%p;
49 }
50 void NTT_main(ll *a,ll *b,ll *c,int len,int l)
51 {
52     NTT(a,len,1);NTT(b,len,1);
53     for(int i=0;i<len;i++) c[i]=(a[i]*b[i])%p;
54     NTT(c,len,-1);
55 }
56
57 int main()
58 {
59     int n,len=1,l=0;scanf("%d",&n);
60     scanf("%s",s1),scanf("%s",s2);
61     for(int i=0;i<n;i++) A[n-i-1]=s1[i]-‘0‘;
62     for(int i=0;i<n;i++) B[n-i-1]=s2[i]-‘0‘;
63     while(len<n+n) len<<=1,l++;
64     pre(len,l);
65     NTT_main(A,B,C,len,l);
66     for(int i=0;i<len;i++)
67         if(C[i]>9) C[i+1]+=C[i]/10,C[i]%=10;
68     int j=len;
69     while(C[j]==0) j--;
70     while(j>-1) printf("%lld",C[j]),j--;
71     puts("");
72     return 0;
73 }
74
75
76  

原文地址:https://www.cnblogs.com/guapisolo/p/9697111.html

时间: 2024-10-07 21:32:12

模板 NTT 快速数论变换的相关文章

NTT(快速数论变换)用到的各种素数及原根

NTT(快速数论变换)用到的各种素数及原根 g是mod(r * 2 ^ k + 1)的原根 r * 2 ^ k + 1 r k g 3 1 1 2 5 1 2 2 17 1 4 3 97 3 5 5 193 3 6 5 257 1 8 3 7681 15 9 17 12289 3 12 11 40961 5 13 3 65537 1 16 3 786433 3 18 10 5767169 11 19 3 7340033 7 20 3 23068673 11 21 3 104857601 25 2

快速数论变换(NTT)

今天的A题,裸的ntt,但我不会,于是白送了50分. 于是跑来学一下ntt. 题面很简单,就懒得贴了,那不是我要说的重点. 重点是NTT,也称快速数论变换. 在很多问题中,我们可能会遇到在模意义下的多项式乘法问题,这时传统的快速傅里叶变换可能就无法满足要求,这时候快速数论变换就派上了用场. 考虑快速傅里叶变换的实现,利用单位复根的特殊性质来减少运算,而利用的,就是dft变换的循环卷积特性.于是考虑在模意义下同样具有循环卷积特性的东西. 考虑在模p意义下(p为特定的质数,满足p=c?2n+1) 我

快速数论变换(NTT)

转自ACdreamers (http://blog.csdn.net/acdreamers/article/details/39026505) 在上一篇文章中 http://blog.csdn.net/acdreamers/article/details/39005227 介绍了用快速傅里叶变 换来求多项式的乘法.可以发现它是利用了单位复根的特殊性质,大大减少了运算,但是这种做法是对复数系数的矩阵 加以处理,每个复数系数的实部和虚部是一个正弦及余弦函数,因此大部分系数都是浮点数,我们必须做复数及

数论 (大数,小费马定理,欧拉定理,威尔逊定理,快速数论变换(NNT)模版)

1 Java大数 2 import java.util.*; 3 import java.math.*; 4 public class Main{ 5 public static void main(String args[]){ 6 Scanner cin = new Scanner(System.in); 7 BigInteger a, b; 8 9 //以文件EOF结束 10 while (cin.hasNext()){ 11 a = cin.nextBigInteger(); 12 b

快速数论变换模板(NTT)

快速数论变化(NTT)是的原理其实和快速傅里叶变换是一样的原理. 对于形如m= c*2^n+1的费马素数,假设其原根为g.那么瞒住g^(m-1)==1  而且正好(m-1)能整除2^n的.所所以可以在模p域进行NTT变换.旋转因子为  g^((m-1)/n).其他的原理都和FFT的原理相同.这样可以解决特殊情况下FFT的浮点误差. /* * Author: islands * Created Time: 2015/7/30 9:25:47 * File Name: test.cpp */ #in

快速数论变换NTT模板

51nod 1348 乘积之和 #include <cmath> #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <queue> #include <map> #include <bitset> #include <set>

BZOJ 3992 Sdoi2015 序列统计 快速数论变换

题目大意:给定n(n<=10^9),质数m(3<=m<=8000),1<=x=m,以及一个[0,m-1]区间内的集合S,求有多少长度为n的数列满足每个元素都属于集合S且所有元素的乘积mod m后=x 求原根,对S集合内每个元素取指标,然后搞出生成函数f(x) 那么答案就是(f(x))^n (mod x^(m-1),mod 1004535809) 上NTT用多项式快速幂搞一搞就好了 #include <cstdio> #include <cstring> #i

BZOJ 3992: [SDOI2015]序列统计 [快速数论变换 生成函数 离散对数]

3992: [SDOI2015]序列统计 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 1017  Solved: 466[Submit][Status][Discuss] Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S. 小C用这个生成器生成了许多这样的数列.但是小C有一个问题需要你的帮助:给定整数x,求所有可以生成出的,且满足数列中

快速傅立叶变换(FFT)相关内容汇总

FFT是近年考察非常频繁的算法,与其相关的知识点也相当多样. 这里主要是资料汇总,内容补充和总结等.具体应用应在各大OJ上做相关题目. 目录: 概述 1. 前置技能:数学基础 1.1 多项式概念与运算. 1.2 微积分初步与泰勒展开 1.3 普通型生成函数与指数型生成函数 1.4 线性代数相关(矩阵,行列式与特征多项式) 1.5 组合数与伯努利数 1.6 常系数齐次线性递推 1.7 初等数论与初等代数 1.8 卷积概念与O(n^2)求法 1.9 拉格朗日插值法 2. FFT:快速傅立叶变换算法总