Kyopro Library
 
読み取り中…
検索中…
一致する文字列を見つけられません
ntt.hpp
[詳解]
1#pragma once
2#include"../../kyopro_library/template.hpp"
3#include"../../kyopro_library/others/modcal.hpp"
4
5/// @brief NTT Friendly 素数用 NTT 構造体
6template<ll MOD, ll primitive_root>
7class NTT {
8 int divide_max,n;
9 vector<ll> roots,inv_roots,tmp;
10
11 void ntt(vector<ll>& a, bool inv=false) {
12 int mask=n-1,p=0;
13 for(int i=n>>1; i>=1; i>>=1) {
14 auto& cur=(p&1)?tmp:a;
15 auto& nxt=(p&1)?a:tmp;
16 ll e=inv?roots[p+1]:inv_roots[p+1];
17 ll w=1;
18 for(int j=0; j<n; j+=i) {
19 REP(k,i) nxt[j+k]=(cur[((j<<1)&mask)+k]+w*cur[(((j<<1)+i)&mask)+k])%MOD;
20 (w*=e)%=MOD;
21 }
22 p++;
23 }
24 if(p&1) swap(a,tmp);
25 if(inv) {
26 int inv_sz=ModInv(n,MOD);
27 for(int i=0; i<n; i++) (a[i]*=inv_sz)%=MOD;
28 }
29 }
30
31public:
32 NTT() {
33 divide_max=1;
34 ll n=MOD-1;
35 while(n%2==0) n>>=1,divide_max++;
36 roots=vector<ll>(divide_max+1);
37 inv_roots=vector<ll>(divide_max+1);
38 roots[0]=inv_roots[0]=1;
39 for(int i=1; i<=divide_max; i++) {
40 roots[i]=ModPow(primitive_root,(MOD-1)/(1<<i),MOD);
41 inv_roots[i]=ModInv(roots[i],MOD);
42 }
43 }
44
45 /// @brief a, b の畳み込み mod M を求める
46 vector<ll> convolve(vector<ll> a, vector<ll> b) {
47 n=1;
48 while(n+1<a.size()+b.size()) n<<=1;
49 tmp=vector<ll>(n);
50
51 vector<ll> fa(n), fb(n);
52 for(int i=0; i<a.size(); i++) fa[i]=a[i];
53 for(int i=0; i<b.size(); i++) fb[i]=b[i];
54
55 ntt(fa); ntt(fb);
56 for(int i=0; i<n; i++) (fa[i]*=fb[i])%=MOD;
57 ntt(fa,true);
58
59 while(fa.size()+1>a.size()+b.size()) fa.pop_back();
60 return fa;
61 }
62};
NTT Friendly 素数用 NTT 構造体
Definition ntt.hpp:7
NTT()
Definition ntt.hpp:32
vector< ll > convolve(vector< ll > a, vector< ll > b)
a, b の畳み込み mod M を求める
Definition ntt.hpp:46
ll ModInv(ll a, ll m)
x^(-1) (mod m) を返す
Definition modcal.hpp:18
#define REP(i, n)
Definition template.hpp:5