teamnote history merge
This commit is contained in:
61
2025fall/source/Math/FFTConv.cpp
Normal file
61
2025fall/source/Math/FFTConv.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
using cpx = complex<double>;
|
||||
using vcpx = vector<cpx>;
|
||||
void fft(vcpx &a, bool inv = false) {
|
||||
int n = a.size(), j = 0; assert((n&-n) == n);
|
||||
for(int i=1; i<n; i++) {
|
||||
int bit = (n >> 1);
|
||||
while(j >= bit) {
|
||||
j -= bit; bit >>= 1;
|
||||
}
|
||||
j += bit; if(i < j) swap(a[i], a[j]);
|
||||
}
|
||||
vcpx roots(n/2);
|
||||
prec c = 2 * pi * (inv ? -1 : 1);
|
||||
for(int i=0; i<n/2; i++)
|
||||
roots[i] = cpx(cosl(c * i / n), sinl(c * i / n));
|
||||
|
||||
for(int i=2, step = n/i; i<=n; i<<=1, step = n/i)
|
||||
for(int j=0; j<n; j+=i) for(int k=0; k<i/2; k++) {
|
||||
cpx u = a[j+k], v = a[j+k+i/2]*roots[step*k];
|
||||
a[j+k] = u+v;
|
||||
a[j+k+i/2] = u-v;
|
||||
}
|
||||
if(inv) for(int i=0; i<n; i++) a[i] /= n;
|
||||
}
|
||||
|
||||
ll mod = 1e9+7;
|
||||
vl conv(const vl& AA,const vl& BB) {
|
||||
const ll G = 1<<15;
|
||||
int n = AA.size()+BB.size()-1;
|
||||
int m = 1; while(m < n) m<<=1;
|
||||
int a = AA.size(), b = BB.size();
|
||||
|
||||
vcpx A(m), B(m), C(m), D(m);
|
||||
fors(i, 0, a-1) A[i] = cpx(AA[i]/G, AA[i]%G);
|
||||
fors(i, 0, b-1) B[i] = cpx(BB[i]/G, BB[i]%G);
|
||||
|
||||
fft(A); fft(B);
|
||||
fors(i, 0, m-1) {
|
||||
int j = i?m-i:0;
|
||||
cpx A1 = (A[i]+conj(A[j]))*cpx(0.5, 0);
|
||||
cpx A2 = (A[i]-conj(A[j]))*cpx(0, -0.5);
|
||||
cpx B1 = (B[i]+conj(B[j]))*cpx(0.5, 0);
|
||||
cpx B2 = (B[i]-conj(B[j]))*cpx(0, -0.5);
|
||||
|
||||
C[i] = A1*B1 + A2*B2*cpx(0, 1);
|
||||
D[i] = A2*B1 + A1*B2*cpx(0, 1);
|
||||
}
|
||||
fft(C, true); fft(D, true);
|
||||
|
||||
vl ret(m); ll G1 = G%mod, G2 = (lll)G*G%mod;
|
||||
fors(i, 0, m-1) {
|
||||
ll p = ll(C[i].real()+0.5);
|
||||
ll q = ll(D[i].real()+0.5) + ll(D[i].imag()+0.5);
|
||||
ll r = ll(C[i].imag()+0.5);
|
||||
|
||||
p %= mod; q %= mod; r %= mod;
|
||||
ret[i] = (((lll)p*G2)%mod+((lll)q*G1)%mod+r%mod)%mod;
|
||||
}
|
||||
ret.resize(n);
|
||||
return ret;
|
||||
}
|
||||
Reference in New Issue
Block a user