This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub AlexanderNekrasov/Youthful-Passion-Fruit-teambook
/**
* Author: allvik
* Date: ?
* Description: subset convolution
* Time: O(2^n * n^2) (500 ms n = 20 with pragms)
*/
void transform(int n, int N, vector <int>& b, const vector <int>& a, const vector <int>& pc, bool rev) {
if (!rev) {
b.assign(N << n, 0);
for(int i = 0; i < (int)a.size(); ++i) b[pc[i] + i*N] = a[i];
}
for(int w = 1; w <= (1<<n); ++w) {
for(int d = 0; !(w&(1<<d)); ++d){
int W = N * (w - (1<<d)), dd = N<<d;
for(int i = N * (w - (2<<d)); i < W; ++i) {
if (!rev) b[i + dd] = add(b[i + dd], b[i]);
else b[i + dd] = sub(b[i + dd], b[i]);
}
}
}
}
vector<int> SubsetConvolution(const vector<int>& a, const vector<int>& b){
int n = 0;
while((1 << n) < max(a.size(),b.size())) n++;
int N = n+1;
vector<int> pc(1<<n,0);
for(int i = 1; i < (1<<n); ++i) pc[i] = pc[i - (i&-i)] + 1;
vector<int> bufA, bufB;
transform(n, N, bufA, a, pc, false);
transform(n, N, bufB, b, pc, false);
for(int i = 0; i < (1<<n); i++) {
int I = i * N;
vector<int> Q(N);
for(int ja = 0; ja <= pc[i]; ++ja) {
for(int jb = pc[i] - ja, x = min(n - ja, pc[i]); jb <= x; ++jb){
Q[ja + jb] = add(Q[ja + jb], mul(bufA[ja + I], bufB[jb + I]));
}
}
copy(Q.begin(), Q.end(), bufA.begin() + I);
}
transform(n, N, bufA, a, pc, true);
vector<int> res(1<<n);
for(int i = 0; i<(1<<n); ++i) res[i] = bufA[pc[i] + i*N];
return res;
}
#line 1 "math/SubsetConvolution.cpp"
/**
* Author: allvik
* Date: ?
* Description: subset convolution
* Time: O(2^n * n^2) (500 ms n = 20 with pragms)
*/
void transform(int n, int N, vector <int>& b, const vector <int>& a, const vector <int>& pc, bool rev) {
if (!rev) {
b.assign(N << n, 0);
for(int i = 0; i < (int)a.size(); ++i) b[pc[i] + i*N] = a[i];
}
for(int w = 1; w <= (1<<n); ++w) {
for(int d = 0; !(w&(1<<d)); ++d){
int W = N * (w - (1<<d)), dd = N<<d;
for(int i = N * (w - (2<<d)); i < W; ++i) {
if (!rev) b[i + dd] = add(b[i + dd], b[i]);
else b[i + dd] = sub(b[i + dd], b[i]);
}
}
}
}
vector<int> SubsetConvolution(const vector<int>& a, const vector<int>& b){
int n = 0;
while((1 << n) < max(a.size(),b.size())) n++;
int N = n+1;
vector<int> pc(1<<n,0);
for(int i = 1; i < (1<<n); ++i) pc[i] = pc[i - (i&-i)] + 1;
vector<int> bufA, bufB;
transform(n, N, bufA, a, pc, false);
transform(n, N, bufB, b, pc, false);
for(int i = 0; i < (1<<n); i++) {
int I = i * N;
vector<int> Q(N);
for(int ja = 0; ja <= pc[i]; ++ja) {
for(int jb = pc[i] - ja, x = min(n - ja, pc[i]); jb <= x; ++jb){
Q[ja + jb] = add(Q[ja + jb], mul(bufA[ja + I], bufB[jb + I]));
}
}
copy(Q.begin(), Q.end(), bufA.begin() + I);
}
transform(n, N, bufA, a, pc, true);
vector<int> res(1<<n);
for(int i = 0; i<(1<<n); ++i) res[i] = bufA[pc[i] + i*N];
return res;
}