首页 > 其他分享 >快速数论变换(NTT)

快速数论变换(NTT)

时间:2023-09-16 18:33:40浏览次数:35  
标签:vector 数论 NTT 变换 int base mod lld

在系数均为整数的时候,可以用NTT代替FFT,这样不会出现精度问题。

#include <bits/stdc++.h>
using namespace std;
typedef long long lld;
const int N = 20000005;
const lld g = 3, mod = 998244353;
lld r[N];
lld powe(lld a, lld b) {
    lld base = 1;
    while(b) {
        if(b & 1) base = base * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return base;
}
void init(int M) 
{
    int l = log2(M); r[0] = 0; 
    for(int i = 1; i < M; i++) {
        r[i] = (r[i >> 1] >> 1 | (i & 1) << (l - 1));
    }
}
void NTT(vector <lld> &a, int M, int type) {
	for(int i = 0; i < M; i++) {
        if(i<r[i]) swap(a[i], a[r[i]]);
    }
    lld Wn, w;
    for(int mid = 1; mid < M; mid <<= 1) {
        Wn = powe(g, (mod - 1) / (mid << 1));
        if(type == -1) Wn = powe(Wn, mod - 2);
        int size = mid << 1;
        for(int i = 0; i < M; i += size) {
            int j = i + mid; w = 1;
            for(int k = i; k < j; k++) {
                lld x = a[k], y = w * a[k + mid] % mod;
                a[k] = (x + y) % mod;
                a[k + mid] = (x - y + mod) % mod;
                w = w * Wn % mod;
            }
        }
    }
}
vector<lld> conv(vector<lld> a, vector<lld> b) {
	int siz = a.size() + b.size();
	int M = 1;
	while(M < siz) M <<= 1;
	a.resize(M); b.resize(M); 
    init(M); NTT(a, M, 1); NTT(b, M, 1);
    for(int i = 0; i <= M; i++) {
        a[i] = a[i] * b[i] % mod;
    }
    NTT(a, M, -1);
    lld t = powe(M, mod - 2);
    for(int i = 0; i <= M; i++) {
        a[i] = a[i] * t % mod;
    }
    a.resize(siz);
    return a; 
}
int n, m;
int main() {
    // freopen("data.in", "r", stdin);
    cin >> n >> m;
    vector <lld> a(n + 2), b(m + 2);
    for(int i = 0; i <= n; i++) {
        cin >> a[i];
    }
    for(int i = 0; i <= m; i++) {
        cin >> b[i];
    }
    vector <lld> c = conv(a, b);
    for(int i = 0; i <= n + m; i++) {
        cout << c[i] << " ";
    }
    return 0;
}

标签:vector,数论,NTT,变换,int,base,mod,lld
From: https://www.cnblogs.com/mcggvc/p/17707088.html

相关文章

  • 一个简单的 Python 实现希尔伯特-黄变换(Hilbert-Huang Transform,简称HHT)的例子
     importnumpyasnpfromscipy.signalimportargrelextremadefemd(data):"""经验模式分解(EmpiricalModeDecomposition,EMD)"""#找到极值点max_points,min_points=argrelextrema(data,np.greater,axis=0)max......
  • P251——用RadialGradientBrush填充椭圆,并进行RotateTransform变换
    一、认识RadialGradientBrush(径向渐变)    1.坐标      RadialGradientBrush可以用来填充矩形(正方形)和椭圆(正圆),      填充区域使用比例坐标,      椭圆的坐标(0,0)和(1,1)构成的矩形内切于椭圆2.设置径向渐变颜色GradientStop<Gradi......
  • 数论有关题
    tax题目:小码哥要交税,交的税钱是收入\(n\)的最大因子(该最大因子为不等于\(n\)的最大因子),但是现在小码哥为了避税,把钱拆成几份(每份至少为\(2\)),使交税最少,输出税钱。格式:输入格式:一个正整数\(n\)表示所以的钱数。输出格式:输出一个正整数,表示税钱。样例:输入:4输出:2备注......
  • 快速傅里叶变换计算多项式乘法
    前言OI中,多项式有着十分广泛的应用。其基础是多项式的基本运算,几乎所有多项式运算都是由多项式加法和乘法拼接成的。我们有显然的\(O(n)\)的办法计算多项式加法,而朴素的多项式乘法是很多情况下难以接受的\(O(n^2)\)的复杂度。快速傅里叶变换(FFT)可以高效(\(O(n\logn)\))计算多......
  • DC-DC升压变换器直流隔离升压模块电源5v12v24v48v转60v80v110v150v220v250v300v500v80
    特点 效率高达80%以上 1*2英寸标准封装 单电压输出 价格低 稳压输出 工作温度:-40℃~+85℃ 阻燃封装,满足UL94-V0要求 温度特性好 可直接焊在PCB上应用HRBW2~40W系列模块电源是一种DC-DC升压变换器。该模块电源的输入电压分为:4.5~9V、9~18V、及18~36V、36~72VDC标准(2......
  • c++中的数论知识
    写在开头:word的公式打不上来,只能截图了一.组合数学(1)加法定理与乘法原理加法原理:做一件事情,完成它可以有n类办法,在第一类办法中有m1种不同的方法,在第二类办法中有m2种不同的方法,……,在第n类办法中有mn种不同的方法。那么完成这件事共有N=m1+m2+…+mn种不同的方法。乘法原理:做一......
  • 字体颜色变换与阴影效果实现字体变大幻觉
    定义元素<divclass="myText">342342</div>CSS按照如下设置,hover时将体验到字体动态凸出的视觉效果.myText{background-color:black;font-family:'PingFangSC','HelveticaNeue','Helvetica','Ari......
  • Matlab短时傅里叶变换和小波变换的时频分析
    ✅作者简介:热爱科研的算法开发者,Python、Matlab项目可交流、沟通、学习。......
  • 数论杂谈
    数论杂谈记录一些小小的东西贝尔数(bell)\(Bell(n)\)(\(B_n\))表示有\(n\)个元素的集合划分成若干个互不相交的子集的方案数\[B_0=1,B_1=1,B_2=2,B_3=5,\dots\]\[B_0=1,B_{n+1}=\sum_{i=0}^nC_n^i\timesB_i\]......
  • 数论基础
    莫比乌斯反演定义先讲讲莫比乌斯函数的定义:\(\mu(x)=\begin{cases}1&n=1\\0&n含有平方因子\\(-1)^k&k为n的本质不同质因子个数\end{cases}\)我们对\(n\)进行质因数分解,\(n=\prod_{i=1}^kp_i^{c_i}\),其中\(p_i\)是质因子,而\(c_i\ge1\).\(n=1\),\(\mu(n)=......