Kyopro Library
 
読み取り中…
検索中…
一致する文字列を見つけられません
convolution_ll.hpp
[詳解]
1#include"../../kyopro_library/template.hpp"
2#include"../../kyopro_library/others/modcal.hpp"
3#include"../../kyopro_library/math/ntt.hpp"
4
5/// @brief x=ai mod mi を満たす x mod m を返す
6ll Garner(vector<ll> a, vector<ll> m, ll mod=INFL+3) {
7 m.push_back(mod);
8 int n=a.size();
9 vector<ll> kp(n+1), rm(n+1,1ll);
10 for(int i=0; i<n; i++) {
11 ll x=((a[i]-kp[i]+m[i])%m[i])*ModInv(rm[i],m[i]);
12 x%=m[i];
13 for(int j=i+1; j<=n; j++) {
14 (kp[j]+=rm[j]*x)%=m[j];
15 (rm[j]*=m[i])%=m[j];
16 }
17 }
18 return kp[n];
19}
20
21/// @brief a, b の自然数での畳み込みを返す
22/// @tparam USE 使う素数の個数
23/// @brief `USE=1` 最終的な配列の値が `X < 1224736769 = 1.2*10^9 = 2^30`
24/// @brief `USE=2` 最終的な配列の値が `X < 575334854091079681 = 5.8*10^17 = 2^59`
25/// @brief `USE=3` 最終的な配列の値が `X < 2^86`
26template<int USE>
27vector<ll> ConvolveInt64(vector<ll> a, vector<ll> b, ll mod=INFL+3) {
28 constexpr const ll MOD1=1224736769, P1=3;
29 constexpr const ll MOD2=469762049, P2=3;
30 constexpr const ll MOD3=167772161, P3=3;
31 static NTT<MOD1,P1> ntt1; static NTT<MOD2,P2> ntt2; static NTT<MOD3,P3> ntt3;
32
33 if(USE==1) {
34 auto c=ntt1.convolve(a,b);
35 vector<ll> ret(c.size());
36 for(int i=0; i<ret.size(); i++) ret[i]=c[i]%mod;
37 return ret;
38 }
39
40 if(USE==2) {
41 auto c1=ntt1.convolve(a,b);
42 auto c2=ntt2.convolve(a,b);
43
44 vector<ll> ret(c1.size());
45 for(int i=0; i<ret.size(); i++) ret[i]=Garner({c1[i],c2[i]}, {MOD1,MOD2}, mod);
46 return ret;
47 }
48
49 auto c1=ntt1.convolve(a,b);
50 auto c2=ntt2.convolve(a,b);
51 auto c3=ntt3.convolve(a,b);
52
53 vector<ll> ret(c1.size());
54 for(int i=0; i<ret.size(); i++) ret[i]=Garner({c1[i],c2[i],c3[i]}, {MOD1,MOD2,MOD3}, mod);
55 return ret;
56}
NTT Friendly 素数用 NTT 構造体
Definition ntt.hpp:7
vector< ll > ConvolveInt64(vector< ll > a, vector< ll > b, ll mod=INFL+3)
a, b の自然数での畳み込みを返す
ll Garner(vector< ll > a, vector< ll > m, ll mod=INFL+3)
x=ai mod mi を満たす x mod m を返す
const ll INFL
Definition template.hpp:13