NTT学习笔记

NTT学习笔记

\((a,p)=1,p >1\)

那么对于满足 \(a^r\equiv 1 \pmod p\)最小的\(r\),称为\(a\)\(p\)的阶,记作\(\delta_p(a)\)

原根

对于正整数\(p\),若有整数\(a\),满足\(\delta_p(a)=\varphi(p)\),称\(a\)\(p\)的一个原根。

  • 原根\(a^0,a^1,\dots,a^{\varphi(p)-1}\)遍历\(\bmod p\)的剩余系

  • \(p\)有原根,那么它一定有\(\varphi(\varphi(p))\)个原根

  • 原根的分布,\(2,4,p^a,2p^a,\dots\),其中\(p\)为素数且\(a\ge 1\)

有限制的NTT

考虑使用原根替代单位根,则需要满足以下一些性质

  • \(w_n^k\)互异
  • \((w_{2n}^k)^2=w_n^k\),折半引理
  • \(w_n^a*w_n^b=w_n^{ab}\)
  • \(w_n^{\frac{n}{2}}=-1\)
  • \(\sum\limits_{i=0}^{n-1} w_n^i=0\),进行逆变换

于是我们用原根这样定义,\(w_n^k=(g^{\frac{p-1}{n}})^k\)

其中\(g\)是质数\(p\)的原根,质数\(p\)被表示成\(p=an+1\)的形式,\(n\)\(2\)的正整数幂。

利用原根的性质和代入计算式,可以验证上面的性质是正确的。

然后其他的和\(FFT\)一样就可以了。

\(p\)一般取\(998244353,1004535809,469762049\),这三个数的原根都是\(3\)

#include <cstdio>
#include <algorithm>
#define ll long long
const int N=(1<<21)+10;
const ll mod=998244353,G=3,Gi=332748118;
ll a[N],b[N];int n,m,turn[N],len=1,L=-1;
ll quickpow(ll d,ll k)
{
    ll f=1;
    while(k)
    {
        if(k&1) f=f*d%mod;
        d=d*d%mod;
        k>>=1;
    }
    return f;
}
void NTT(ll *a,int typ)
{
    for(int i=0;i<len;i++)
        if(i<turn[i])
            std::swap(a[i],a[turn[i]]);
    for(int le=1;le<len;le<<=1)
    {
        ll wn=quickpow(typ?G:Gi,(mod-1)/(le<<1));
        for(int p=0;p<len;p+=le<<1)
        {
            ll w=1;
            for(int i=p;i<p+le;i++,w=w*wn%mod)
            {
                ll tmpx=a[i],tmpy=w*a[i+le]%mod;
                a[i]=(tmpx+tmpy)%mod;
                a[i+le]=(tmpx-tmpy)%mod;
            }
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=0;i<=n;i++) scanf("%lld",a+i);
    for(int i=0;i<=m;i++) scanf("%lld",b+i);
    while(len<=n+m) len<<=1,++L;
    for(int i=0;i<len;i++) turn[i]=turn[i>>1]>>1|(i&1)<<L;
    NTT(a,1),NTT(b,1);
    for(int i=0;i<len;i++) a[i]=a[i]*b[i]%mod;
    NTT(a,0);
    ll inv=quickpow(len,mod-2);
    for(int i=0;i<=n+m;i++) printf("%lld ",(a[i]*inv%mod+mod)%mod);
    return 0;
}

任意模数NTT

看了一下,暂时感觉意义不大,先咕咕掉

posted @ 2018-12-06 17:36  露迭月  阅读(503)  评论(0编辑  收藏  举报