快速数论变换(NTT)

原创 2015年07月08日 20:29:49

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

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef double db;

const int inf=0x3f3f3f3f;

int getint()
{
    int f=1,g=0;char c=getchar();
    while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0' && c<='9')g=(g<<3)+(g<<1)+c-'0',c=getchar();
    return f*g;
}

const int maxn=300005;
const int mod=998244353;

const int G=3;

int a[maxn];
int b[maxn];
int c[maxn];
int n,m;
int rev[maxn];
int N;
int len;
int inv;

int power(ll x,ll y)
{
    ll res=1ll;
    for(;y;y>>=1,x=(x*x)%mod)
    {
        if(y&1)res=(res*x)%mod;
    }
    return res;
}

void init()
{
    while((n+m)>=(1<<len))len++;
    N=(1<<len);
    inv=power(N,mod-2);
    for(int i=0;i<N;i++)
    {
        int pos=0;
        int temp=i;
        for(int j=1;j<=len;j++)
        {
            pos<<=1;pos |= temp&1;temp>>=1;
        }
        rev[i]=pos;
    }
}

void ntt(int *a,int n,int re)
{
    for(int i=0;i<n;i++)
    {
        if(rev[i]>i)
        {
            swap(a[i],a[rev[i]]);
        }
    }
    for(int i=2;i<=n;i<<=1)
    {
        int mid=i>>1;

        int wn=power(G,(mod-1)/i);
        if(re) wn=power(wn,(mod-2));
        for(int j=0;j<n;j+=i)
        {
            int w=1;
            for(int k=0;k<mid;k++)
            {
                int temp1=a[j+k];
                int temp2=(ll)a[j+k+mid]*w%mod;
                a[j+k]=(temp1+temp2);if(a[j+k]>=mod)a[j+k]-=mod;
                a[j+k+mid]=(temp1-temp2);if(a[j+k+mid]<0)a[j+k+mid]+=mod;
                w=(ll)w*wn%mod;
            }
        }
    }
    if(re)
    {
        for(int i=0;i<n;i++)
        {
            a[i]=(ll)a[i]*inv%mod;
        }
    }
}

int main()
{
    n=getint();
    m=getint();

    for(int i=0;i<=n;i++)
    {
        a[i]=getint();
    }
    for(int i=0;i<=m;i++)
    {
        b[i]=getint();      
    }

    init();

    ntt(a,N,0);
    ntt(b,N,0);
    for(int i=0;i<=N;i++)
    {
        c[i]=(ll)a[i]*b[i]%mod;
    }
    ntt(c,N,1);
    for(int i=0;i<=n+m;i++)
    {
        printf("%d%c",c[i]," \n"[i==n+m]);
    }

    return 0;
}

快速数论变换(NTT)

FFT的复数精度问题让我很不爽,很早
  • zz_1215
  • zz_1215
  • 2014年10月24日 16:58
  • 11244

快速数论变换模板(NTT)

快速数论变化(NTT)是的原理其实和快速傅里叶变换是一样的原理。 对于形如m= c*2^n+1的费马素数,假设其原根为g。那么瞒住g^(m-1)==1  而且正好(m-1)能整除2^n的。所所以可以在...
  • u012127882
  • u012127882
  • 2015年07月31日 20:32
  • 1941

NTT(快速数论变换)

大佬博客 和FFT一样都是快速求多项式乘法的,但是这个用的是整数,没有精度误差,运算起来也会更快。#include #include #include #include #include ...
  • ACMer_ZP
  • ACMer_ZP
  • 2017年08月04日 16:20
  • 107

NTT FFT 数论变换 快速傅里叶变换 模板

关于傅里叶变换和数论变换
  • cFarmerReally
  • cFarmerReally
  • 2016年09月29日 12:34
  • 894

快速傅里叶变换(FFT)和数论变换(NTT)模板

#include #define ll long long #define dob complex const int N=120010; const double pi=acos(-1.0); us...
  • pan1197349032
  • pan1197349032
  • 2016年09月04日 15:39
  • 508

【模板】快速数论变换ntt

转自http://blog.csdn.net/zz_1215/article/details/40430041 快速数论变换模板: #include #include #include...
  • Summer_via
  • Summer_via
  • 2016年10月13日 08:54
  • 136

NTT(快速数论变换)模板

例题: HDU 1402#include #include #include #include #include using namespace std; const double PI =...
  • qingshui23
  • qingshui23
  • 2017年06月14日 12:53
  • 270

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

题目大意:给定n(n 求原根,对S集合内每个元素取指标,然后搞出生成函数f(x) 那么答案就是(f(x))^n (mod 1004535809) 上NTT用多项式快速幂搞一搞就好了 #in...
  • PoPoQQQ
  • PoPoQQQ
  • 2015年04月15日 20:50
  • 2987

新知——快速数论变换

快速数论变换 学习笔记
  • kyleyoung_ymj
  • kyleyoung_ymj
  • 2016年08月15日 22:34
  • 1415

[NTT] 快速数论变换学习笔记

FNT和NTT都是快速数论变换
  • HeRaNO
  • HeRaNO
  • 2017年05月05日 23:22
  • 1198
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:快速数论变换(NTT)
举报原因:
原因补充:

(最多只允许输入30个字)