zoukankan      html  css  js  c++  java
  • NTT学习笔记

    NTT学习笔记

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

    那么对于满足 (a^requiv 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})遍历(mod p)的剩余系

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

    • 原根的分布,(2,4,p^a,2p^a,dots),其中(p)为素数且(age 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)
    • (sumlimits_{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

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

  • 相关阅读:
    spring+ springmvc + websocket+sockjs 404/200
    spring+ springmvc + websocket+sockjs 404/200
    Java中assert(断言)的使用
    Java中assert(断言)的使用
    shiro 静态页面资源不显示 解决方案
    shiro 静态页面资源不显示 解决方案
    彻底解决 intellij IDEA 卡顿 优化笔记
    彻底解决 intellij IDEA 卡顿 优化笔记
    bigdecimal 保留小数位
    bigdecimal 保留小数位
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10078066.html
Copyright © 2011-2022 走看看