精华内容
下载资源
问答
  • NTT

    2015-08-11 23:34:14
    NTT

    我觉得我还需要理解一下 FFT 和 NTT …


    #include <cstdio>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    
    const int maxn = 4e4+5, Mod = 950009857;
    const int G = 7;
    
    int n, m, k, N = 1;
    long long g[maxn], invN;
    long long f[maxn], c[maxn];
    long long p[maxn];
    
    long long power(long long x,int t)
    {
        long long ret = 1;
        while(t)
        {
            if(t&1) ret *= x, ret %= Mod;
            x *= x, x %= Mod, t >>= 1;
        }
        return ret;
    }
    void PreWork()
    {
        while(N <= (n<<1)) N <<= 1;
    
        invN = power(N, Mod - 2);
    
        g[0] = g[N] = 1, g[1] = power(G, (Mod-1)/N); 
        for(int i = 2; i < N; i++)
            g[i] = g[i-1] * g[1] % Mod;
    
    }
    void NTT(long long a[],int len,int flag)
    {
        for(int i = 0; i < len; i++)
        {
            int s = i, p = 0;
            for(int j = len>>1; j > 0; j >>= 1)
                p |= (s&1)*j, s >>= 1;
            if(p > i) std::swap(a[p], a[i]);
        }
        for(int L = 2 ; L <= len; L <<= 1)
            for(int i = 0; i < len ; i += L)
                for(int j = 0; j < (L>>1); j++)
                {
                    long long w = (flag == 1)?g[N/L*j]:g[N - N/L*j];
                    long long u = a[i + j], v = a[i + j +(L>>1)]*w % Mod;
                    u += v, v = u - (v<<1), a[i + j] = u % Mod;
                    a[i + j +(L>>1)] = (v + Mod) % Mod;
                }
    
        if(flag == -1)
            for(int i = 0; i < len; i++)
                a[i] = a[i] * invN % Mod;
    }

    展开全文
  • ntt

    2019-10-23 21:04:10
    #include<bits/stdc++.h> using namespace std; #define mo 998244353 char cc[100010],*dd = cc + 100000; //#define gc ((dd == cc + 100000 ? (fread(cc,1,100000,stdin),dd = cc) : 0),*(dd++)) ...
    #include<bits/stdc++.h>
    using namespace std;
    #define mo 998244353
    char cc[100010],*dd = cc + 100000;
    //#define gc ((dd == cc + 100000 ? (fread(cc,1,100000,stdin),dd = cc) : 0),*(dd++))
    #define gc getchar()
    #define ll long long
    ll a[2100010],b[2100010],c[2100010],n,m,tmp[2100010];
    inline int read(){
    	int x = 0,c = gc;
    	while(!isdigit(c)) c = gc;
    	while(isdigit(c)) x = x * 10 + c - '0',c = gc;
    	return x;
    }
    inline void print(int x){
    	if(x >= 10) print(x / 10);
    	putchar(x % 10 + '0');
    }
    ll ksm(ll a,ll b){
    	ll as = 1;
    	while(b){
    		if(b & 1) as = as * a % mo;
    		a = a * a % mo;
    		b >>= 1;
    	}
    	return as;
    }
    ll wn[2100010],nwn[2100010];
    void work(ll *a,int n,bool fg){
    	if(n == 1) return;
    	int i,mid = n / 2;
    	for(i = 0;i < mid;++i){
    		tmp[i] = a[i << 1];
    		tmp[i + mid] = a[i << 1 | 1];
    	}
    	for(i = 0;i < n;++i) a[i] = tmp[i];
    	work(a,mid,fg);work(a + mid,mid,fg);
    	ll wnn,nw = 1,w1,w2;
    	wnn = fg ? wn[n] : nwn[n];
    	for(i = 0;i < mid;++i){
    		w1 = a[i];w2 = a[i + mid] * nw % mo;
    		a[i] = (w1 + w2) % mo;
    		a[i + mid] = (w1 - w2 + mo) % mo;
    		(nw *= wnn) %= mo;
    	}
    }
    void mmul(ll *a,ll *b,ll *c,int n){
    	work(a,n,1);work(b,n,1);
    	for(int i = 0;i < n;++i) c[i] = a[i] * b[i] % mo;
    	work(c,n,0);
    	ll ny = ksm(n,mo - 2);
    	for(int i = 0;i < n;++i) (c[i] *= ny) %= mo;
    }
    int main(){
    	int i,l;
    	n = read() + 1;m = read() + 1;
    	for(i = 0;i < n;++i) a[i] = read();
    	for(i = 0;i < m;++i) b[i] = read();
    	m += n;
    	for(l = 1;l < m;l <<= 1);
    	n = l;
    	for(;l;l >>= 1){
    		wn[l] = ksm(3,(mo - 1) / l);
    		nwn[l] = ksm(3,mo - 1 - (mo - 1) / l);
    	}
    	mmul(a,b,c,n);
    	for(i = 0;i < m - 1;++i) print(c[i]),putchar(' ');putchar('\n');
    	return 0;
    }

     

    展开全文
  • 恩特 数论变换(NTT) 我在NTT进行试验的游乐场。
  • NTT ideas

    2020-12-08 21:20:07
    <div><p>I recently wrote some NTT code for my Leopard project and found a 50% speed boost using decimation-in-time version, where I take groups of 4 positions and operate on them (rather than 2 at a ...
  • [NTT]任意模数NTT

    2019-12-19 20:16:40
    NTT FFT可以帮助我们快速地将多项式从系数表达变换成点值表达。但由于涉及浮点数运算,我们需要对一些数取模时,不能一边计算一边取模,所以有可能会爆炸。而且我们有时候也会因此丢失精度,导致结果错误。所以,...

    题目

    洛谷

    NTT

    FFT可以帮助我们快速地将多项式从系数表达变换成点值表达。但由于涉及浮点数运算,我们需要对一些数取模时,不能一边计算一边取模,所以有可能会爆炸。而且我们有时候也会因此丢失精度,导致结果错误。所以,我们就要引入NTT算法。

    NTT是利用一些特殊的模数,基于数论来进行变换的一种基于FFT的多项式算法。过程中所使用的都是整数,所以不存在这些问题。

    前备知识

    对于gcd(x,n)=1\gcd(x, n) = 1,满足xk1(mod m)x^k \equiv 1 (mod \ m),最小的kk就叫做xxnn的阶。

    原根

    设正整数mm,整数aa,若aamm的阶为ϕm\phi m,则称aa为模mm的一个原根。

    常用原根表

                                                \ \ 质数 \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 原根
      3                                                2\ \ 3\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 2
      5                                                2\ \ 5\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 2
      97                                              5\ \ 97\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 5
      193                                            5\ \ 193\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 5
      257                                            3\ \ 257\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3
      7681                                          17\ \ 7681\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 17
      12289                                        11\ \ 12289\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 11
      40961                                        3\ \ 40961\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3
      65537                                        3\ \ 65537\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3
      786433                                      10\ \ 786433\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 10
      5767169                                    3\ \ 5767169\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3
      7340033                                    3\ \ 7340033\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3
      23068673                                  3\ \ 23068673\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3
      104857601                                2\ \ 104857601\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 2
      167772161                                3\ \ 167772161\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3
      469762049                                3\ \ 469762049\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3
      998244353                                3\ \ 998244353\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3
      1004535809                              3\ \ 1004535809\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3

    NTT

    普通NTT Code:

    void NTT(LL *A,LL Type)
    {
    	for (Int i = 0; i < Limit; ++ i)
    		if (i < R[i])
    			Swap(A[i], A[R[i]]);
    	for (Int i = 1; i < Limit; i <<= 1)
    	{
    		LL Root = QuickPow(Type == 1 ? G : InvG, (AllMod - 1) / (i << 1), AllMod);
    		for (Int j = 0; j < Limit; j += (i << 1))
    		{
    			LL Power = 1;
    			for (Int k = 0; k < i; ++ k, Power = Power * Root % AllMod)
    			{
    				LL x = A[j + k];
    				LL y = Power * A[i + j + k] % AllMod;
    				A[j + k] = (x + y) % AllMod;
    				A[i + j + k] = (x - y + AllMod) % AllMod; 
    			}
    		}
    	}
    	if (Type == -1)
    	{
    		LL Inv = QuickPow(Limit, AllMod - 2, AllMod);
    		for (Int i = 0; i < Limit; ++ i)
    			A[i] = A[i] * Inv % AllMod;
    	}
    }
    

    任意模数NTT(三模数NTT) Code:

    int_128:
     #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define LL long long
    #define MAXN 2097152 + 5
    #define Int register int
    using namespace std;
    const int G = 3;
    const int MOD[4] = {0, 104857601, 167772161, 469762049};
    const int GINV[4] = {0, 34952534, 55924054, 156587350};
    int lena, lenb, len = 1, p;
    int a[4][MAXN], b[4][MAXN], r[MAXN], Ans[4];
    inline int Read()
    {
    	int x = 0, f = 1;
    	char s = getchar();
    	while (s < '0' || s > '9')
    	{
    		if (s == '-')
    			f = -1;
    		s = getchar();
    	}
    	while (s >= '0' && s <= '9')
    	{
    		x = (x << 3) + (x << 1) + (s ^ 48);
    		s = getchar();
    	}
    	return x * f;
    }
    void Putt(int x)
    {
        if (x > 9)
    		Putt(x / 10);
        putchar(x % 10 ^ 48);
    }
    void Write(int x)
    {
        if(x < 0)
    		putchar('-'), x = -x;
        Putt( x );
    }
    inline int Max(int x,int y)
    {
    	return x > y ? x : y;
    }
    inline int Min(int x,int y)
    {
    	return x < y ? x : y;
    }
    void Init()
    {
        int l = -1;
        while (len <= lena + lenb)
        {
            len <<= 1;
            l ++;
        }
        for (Int i = 0; i < len; ++ i)
            r[i] = (r[i >> 1] >> 1) | ((i & 1) << l);
    }
    LL QuickPow(LL x,LL y,LL MOD)
    {
        x %= MOD;
        LL ret = 1;
        while ( y )
        {
            if (y & 1)
                ret = ret * x % MOD;
            x = x * x % MOD;
            y >>= 1;
        }
        return ret;
    }
    void CRT(int *a,int n)
    {
        __int128 Ans = 0, M = 1;
        for (Int i = 1; i <= n; ++ i)
            M *= MOD[i];
        for (Int i = 1; i <= n; ++ i)
        {
            LL MI = M / MOD[i];
            LL ti = QuickPow(MI, MOD[i] - 2, MOD[i]);
            Ans = (Ans + ti * a[i] % M * MI % M) % M;
        }
        Write((Ans % p + p) % p);
        putchar(' ');
    }
    void Swap(int &x,int &y)
    {
    	int temp = x;
    	x = y;
    	y = temp;
    }
    void NTT(int *a,int flg,int cas)
    {
        for (Int i = 0; i < len; ++ i)
            if (i < r[i])
                Swap(a[i], a[r[i]]);
        for (Int s = 1; s < len; s <<= 1)
        {
            LL wn = QuickPow(flg ? G : GINV[cas], (MOD[cas] - 1) / (s << 1), MOD[cas]);
            for (Int i = 0; i < len; i += (s << 1))
            {
                LL w = 1;
                for (Int j = i; j < i + s; ++ j, w = w * wn % MOD[cas])
                {
                    LL x = a[j],y = w * a[j + s] % MOD[cas];
                    a[j] = (x + y) % MOD[cas];
                    a[j + s] = (x - y) % MOD[cas];
                }
            }
        }
    }
    int main()
    {
        lena = Read();
        lenb = Read();
        p = Read();
        for (Int i = 0; i <= lena; ++ i)
    		a[1][i] = a[2][i] = a[3][i] = Read();
        for (Int i = 0; i <= lenb; ++ i)
    		b[1][i] = b[2][i] = b[3][i] = Read();
        Init();
        for (Int cas = 1; cas <= 3; ++ cas)
        {
            NTT(a[cas], 1, cas);
            NTT(b[cas], 1, cas);
            for (Int i = 0; i < len; ++ i)
                a[cas][i] = 1ll * a[cas][i] * b[cas][i] % MOD[cas];
            NTT(a[cas], 0, cas);
        }
        for (Int cas = 1; cas <= 3; ++ cas)
        {
            int inv = QuickPow(len, MOD[cas] - 2, MOD[cas]);
            for (Int i = 0; i <= lena + lenb; ++ i)
                a[cas][i] = ((1ll * a[cas][i] * inv % MOD[cas]) + MOD[cas]) % MOD[cas];
        }
        for (Int i = 0; i <= lena + lenb; ++ i)
        {
            for (Int cas = 1; cas <= 3; ++ cas)
                Ans[cas] = a[cas][i];
            CRT(Ans, 3);
        }
        return 0;
    }
    
    long long:
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define LL long long
    #define MAXN 2097152 + 5
    #define Int register int
    using namespace std;
    const int G = 3;
    const int MOD[4] = {0, 40961, 65537, 5767169};
    const int GINV[4] = {0, 13654, 21846, 1922390};
    int lena, lenb, len = 1, p;
    int a[4][MAXN], b[4][MAXN], r[MAXN], Ans[4];
    inline int Read()
    {
    	int x = 0, f = 1;
    	char s = getchar();
    	while (s < '0' || s > '9')
    	{
    		if (s == '-')
    			f = -1;
    		s = getchar();
    	}
    	while (s >= '0' && s <= '9')
    	{
    		x = (x << 3) + (x << 1) + (s ^ 48);
    		s = getchar();
    	}
    	return x * f;
    }
    void Putt(LL x)
    {
        if (x > 9)
    		Putt(x / 10);
        putchar(x % 10 ^ 48);
    }
    void Write(LL x)
    {
        if (x < 0)
    		putchar('-'), x = -x;
        Putt( x );
    }
    inline int Max(int x,int y)
    {
    	return x > y ? x : y;
    }
    inline int Min(int x,int y)
    {
    	return x < y ? x : y;
    }
    void Init()
    {
        int l = -1;
        while (len <= lena + lenb)
        {
            len <<= 1;
            l ++;
        }
        for (Int i = 0; i < len; ++ i)
            r[i] = (r[i >> 1] >> 1) | ((i & 1) << l);
    }
    LL QuickPow(LL x,LL y,LL MOD)
    {
        x %= MOD;
        LL ret = 1;
        while ( y )
        {
            if (y & 1)
                ret = ret * x % MOD;
            x = x * x % MOD;
            y >>= 1;
        }
        return ret;
    }
    void CRT(int *a,int n)
    {
        LL Ans = 0, M = 1;
        for (Int i = 1; i <= n; ++ i)
            M *= MOD[i];
        for (Int i = 1; i <= n; ++ i)
        {
            LL MI = M / MOD[i];
            LL ti = QuickPow(MI, MOD[i] - 2, MOD[i]);
            Ans = (Ans + ti * a[i] % M * MI % M) % M;
        }
        Write((Ans % p + p) % p);
        putchar(' ');
    }
    void Swap(int &x,int &y)
    {
    	int temp = x;
    	x = y;
    	y = temp;
    }
    void NTT(int *a,int flg,int cas)
    {
        for (Int i = 0; i < len; ++ i)
            if (i < r[i])
                Swap(a[i], a[r[i]]);
        for (Int s = 1; s < len; s <<= 1)
        {
            LL wn = QuickPow(flg ? G : GINV[cas], (MOD[cas] - 1) / (s << 1), MOD[cas]);
            for (Int i = 0; i < len; i += (s << 1))
            {
                LL w = 1;
                for (Int j = i; j < i + s; ++ j, w = w * wn % MOD[cas])
                {
                    LL x = a[j],y = w * a[j + s] % MOD[cas];
                    a[j] = (x + y) % MOD[cas];
                    a[j + s] = (x - y) % MOD[cas];
                }
            }
        }
    }
    int main()
    {
        lena = Read();
        lenb = Read();
        p = Read();
        for (Int i = 0; i <= lena; ++ i)
    		a[1][i] = a[2][i] = a[3][i] = Read();
        for (Int i = 0; i <= lenb; ++ i)
    		b[1][i] = b[2][i] = b[3][i] = Read();
        Init();
        for (Int cas = 1; cas <= 3; ++ cas)
        {
            NTT(a[cas], 1, cas);
            NTT(b[cas], 1, cas);
            for (Int i = 0; i < len; ++ i)
                a[cas][i] = 1ll * a[cas][i] * b[cas][i] % MOD[cas];
            NTT(a[cas], 0, cas);
        }
        for (Int cas = 1; cas <= 3; ++ cas)
        {
            int inv = QuickPow(len, MOD[cas] - 2, MOD[cas]);
            for (Int i = 0; i <= lena + lenb; ++ i)
                a[cas][i] = ((1ll * a[cas][i] * inv % MOD[cas]) + MOD[cas]) % MOD[cas];
        }
        for (Int i = 0; i <= lena + lenb; ++ i)
        {
            for (Int cas = 1; cas <= 3; ++ cas)
                Ans[cas] = a[cas][i];
            CRT(Ans, 3);
        }
        return 0;
    }
    

    然而这个模数里二的幂太小了,基本上用不了

    展开全文
  • NTT-TEST-源码

    2021-03-29 19:56:29
    NTT-TEST
  • ntt.api-源码

    2021-02-11 02:54:05
    ntt.api
  • 任意模数\(NTT\)众所周知,为了满足单位根的性质,\(NTT\)需要质数模数,而且需要能写成\(a2^{k} + 1\)且\(2^k \ge n\)比较常用的有\(998244353,1004535809,469762049\),这三个原根都是\(3\)如果要任意模数怎么办?...

    任意模数\(NTT\)

    众所周知,为了满足单位根的性质,\(NTT\)需要质数模数,而且需要能写成\(a2^{k} + 1\)且\(2^k \ge n\)

    比较常用的有\(998244353,1004535809,469762049\),这三个原根都是\(3\)

    如果要任意模数怎么办?

    \(n\)次多项式在模\(m\)下乘积,最终系数一定不会大于\(nm^2\)

    所以我们找三个模数分别做\(NTT\)再合并一下就好辣

    但这样的合并结果会爆\(long long\)呢

    需要用高精吗?

    可以使用一些技巧

    我们要合并的是

    \[\left \{

    \begin{aligned}

    x \equiv a_1 \pmod {m_1} \\

    x \equiv a_2 \pmod {m_2} \\

    x \equiv a_3 \pmod {m_3} \\

    \end{aligned}

    \right.

    \]

    我们先在\(long long\)范围内合并前两个

    \[\left \{

    \begin{aligned}

    x \equiv A \pmod M \\

    x \equiv a_3 \pmod {m_3} \\

    \end{aligned}

    \right.

    \]

    由于最后结果模\(M\)为\(A\),模\(m_3\)为\(a_3\)

    设最后的答案是

    \[ans = kM + A

    \]

    且\(k\)需要满足

    \[kM + A \equiv a_3 \pmod {m_3}

    \]

    所以\(k\)一定是在模\(m_3\)意义下求出的,为

    \[k \equiv (a_3 - A)M^{-1} \pmod {m_3}

    \]

    求出\(k\)后就可以直接在原模数意义下求出

    \[ans = kM + A

    \]

    在第一次合并的时候需要快速乘

    做三次\(NTT\)常数有够大的

    #include

    #include

    #include

    #include

    #include

    #include

    #include

    #include

    #include

    #define LL long long int

    #define REP(i,n) for (int i = 1; i <= (n); i++)

    #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)

    #define cls(s,v) memset(s,v,sizeof(s))

    #define mp(a,b) make_pair(a,b)

    #define cp pair

    using namespace std;

    const int maxn = 400005,maxm = 100005,INF = 0x3f3f3f3f;

    inline int read(){

    int out = 0,flag = 1; char c = getchar();

    while (c < 48 || c > 57){if (c == '-') flag = 0; c = getchar();}

    while (c >= 48 && c <= 57){out = (out << 1) + (out << 3) + c - 48; c = getchar();}

    return flag ? out : -out;

    }

    int pr[]={469762049,998244353,1004535809};

    int R[maxn];

    inline LL qpow(LL a,LL b,LL p){

    LL re = 1; a %= p;

    for (; b; b >>= 1,a = a * a % p)

    if (b & 1) re = re * a % p;

    return re;

    }

    struct FFT{

    int G,P,A[maxn];

    void NTT(int* a,int n,int f){

    for (int i = 0; i < n; i++) if (i < R[i]) swap(a[i],a[R[i]]);

    for (int i = 1; i < n; i <<= 1){

    int gn = qpow(G,(P - 1) / (i << 1),P);

    for (int j = 0; j < n; j += (i << 1)){

    int g = 1,x,y;

    for (int k = 0; k < i; k++,g = 1ll * g * gn % P){

    x = a[j + k],y = 1ll * g * a[j + k + i] % P;

    a[j + k] = (x + y) % P,a[j + k + i] = (x + P - y) % P;

    }

    }

    }

    if (f == 1) return;

    int nv = qpow(n,P - 2,P); reverse(a + 1,a + n);

    for (int i = 0; i < n; i++) a[i] = 1ll * a[i] * nv % P;

    }

    }fft[3];

    int F[maxn],G[maxn],B[maxn],deg1,deg2,deg,md;

    LL ans[maxn];

    LL inv(LL n,LL p){return qpow(n % p,p - 2,p);}

    LL mul(LL a,LL b,LL p){

    LL re = 0;

    for (; b; b >>= 1,a = (a + a) % p)

    if (b & 1) re = (re + a) % p;

    return re;

    }

    void CRT(){

    deg = deg1 + deg2;

    LL a,b,c,t,k,M = 1ll * pr[0] * pr[1];

    LL inv1 = inv(pr[1],pr[0]),inv0 = inv(pr[0],pr[1]),inv3 = inv(M % pr[2],pr[2]);

    for (int i = 0; i <= deg; i++){

    a = fft[0].A[i],b = fft[1].A[i],c = fft[2].A[i];

    t = (mul(a * pr[1] % M,inv1,M) + mul(b * pr[0] % M,inv0,M)) % M;

    k = ((c - t % pr[2]) % pr[2] + pr[2]) % pr[2] * inv3 % pr[2];

    ans[i] = ((k % md) * (M % md) % md + t % md) % md;

    }

    }

    void conv(){

    int n = 1,L = 0;

    while (n <= (deg1 + deg2)) n <<= 1,L++;

    for (int i = 1; i < n; i++) R[i] = (R[i >> 1] >> 1) | ((i & 1) << (L - 1));

    for (int u = 0; u <= 2; u++){

    fft[u].G = 3; fft[u].P = pr[u];

    for (int i = 0; i <= deg1; i++) fft[u].A[i] = F[i];

    for (int i = 0; i <= deg2; i++) B[i] = G[i];

    for (int i = deg2 + 1; i < n; i++) B[i] = 0;

    fft[u].NTT(fft[u].A,n,1); fft[u].NTT(B,n,1);

    for (int i = 0; i < n; i++) fft[u].A[i] = 1ll * fft[u].A[i] * B[i] % pr[u];

    fft[u].NTT(fft[u].A,n,-1);

    }

    }

    int main(){

    deg1 = read(); deg2 = read(); md = read();

    for (int i = 0; i <= deg1; i++) F[i] = read();

    for (int i = 0; i <= deg2; i++) G[i] = read();

    conv(); CRT();

    for (int i = 0; i <= deg; i++) printf("%lld ",ans[i]);

    return 0;

    }

    展开全文
  • ntt_template-源码

    2021-03-28 09:36:00
    ntt_template :该部分ntt 模板git repo,用于创建具有cmake支持,示例和单元测试的ntt型库。 编写新库时,最好从此存储库中进行克隆。 用cmake添加 您可以通过cmake将任何ntt-库添加到项目中。 在主项目目录中...
  • NTT模板

    2018-12-31 22:53:11
    //by waynetuinfor const int maxn = ; const int mod = ; const int root = ; template &...long long mod, long long root&...struct NTT { vector&lt;long long&gt; omega; NTT() { omega.re...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,394
精华内容 1,357
关键字:

NTT