博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
hdu 6057 Kanade's convolution(子集卷积)
阅读量:4580 次
发布时间:2019-06-09

本文共 1884 字,大约阅读时间需要 6 分钟。

题解:

然后就是接下来如何fwt

也就是如何处理bit(x) - bit(y) = bit(k)这个条件。

其实就是子集卷积。

把bit(x)和bit(y)划分成两个集合,然后就是子集卷积的形式。

这里设两个新的数组 A[bit(y)][y], B[bit(x)][x],代表拆出来的相应数组

然后对这两个数组做fwt,得到其点值表示,然后直接在外层枚举x和y的大小然后做卷积即可。

这样说可能很抽象,其实贴出代码就很清楚了

 

#include 
#include
#include
using namespace std;const int MOD = 998244353;typedef long long LL;LL mypow(LL a, LL b){ LL ans = 1; for(; b; b >>= 1) { if(b&1) (ans *= a) %= MOD; (a *= a) %= MOD; } return ans;}LL I2 = mypow(2, MOD-2);const int maxn = (1<<19) + 100;LL a[maxn], b[maxn], A[21][maxn*4], B[21][maxn*4], C[21][maxn*4];vector
Bit[21];int m;class FWT{public: void fwt(LL *a, int n){ for(int d = 1; d < n; d <<= 1){ for(int m = d<<1, i = 0; i < n; i += m){ for(int j = 0; j < d; j++){ LL x = a[i+j], y = a[i+j+d]; a[i+j] = x+y; if(a[i+j] >= MOD) a[i+j] -= MOD; a[i+j+d] = x-y; if(a[i+j+d] < 0) a[i+j+d] += MOD; } } } } void ufwt(LL *a, int n){ for(int d = 1; d < n; d <<= 1){ for(int m = d<<1, i = 0; i < n; i += m){ for(int j = 0; j < d; j++){ LL x = a[i+j], y = a[i+j+d]; a[i+j] = (x+y)*I2%MOD; a[i+j+d] = (x-y+MOD)*I2%MOD; } } } } void work(LL *a, LL *b, int n){ fwt(a, n); fwt(b, n); for(int i = 0; i < n; i++) a[i] *= b[i]; ufwt(a, n); }}myfwt;int bit(int x){ int ans = 0; for(int i = 0; i < 19; i++) ans += ((x&(1<
0); return ans;}int main(){ for(int i = 0; i < (1<<19); i++) Bit[bit(i)].push_back(i); cin>>m; for(int i = 0; i < (1<
= L) break; A[i][x] = (a[x]*(1<

 

转载于:https://www.cnblogs.com/Saurus/p/7374604.html

你可能感兴趣的文章