CF1301 Little C Loves 3 III

很巧妙的题,显然子集卷积很傻。

$cnt[i]$为二进制$1$的数量

  • $i\&j!=0,cnt[i]+cnt[j]>cnt[i|j]$
  • $i\&j=0,cnt[i]+cnt[j]=cnt[i|j]$

构造$a[i]=a_i\times 4^{cnt[i]},b[i]=b_i\times 4^{cnt[i]}$

$FWTor\rightarrow,c[k]=\sum _{i|j=k,i\& j=0} a_j\times b_i\times 4^{cnt[i]+cnt[j]}$

$c[k]/4^{cnt[k]]}\mod 4$,就只剩下我们需要的部分了。

代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
#define mk make_pair
const int N = (1 << 21) + 100;

void FWT(ll *A, int n, int op, int t) //t=1 or t=2 and t=3 xor
{
for (int i = 2; i <= n; i <<= 1)
{
for (int j = 0, mid = i >> 1; j < n; j += i)
for (int k = 0; k < mid; k++)
{

if (t == 1)
A[j + mid + k] = A[j + mid + k] + A[j + k] * op;
// else if (t == 2)
// A[j + k] = inc(A[j + k], A[j + mid + k] * op, mod);
// else if (t == 3)
// {
// int x = A[j + k], y = A[j + mid + k];
// if (op == 1)
// A[j + k] = (x + y) % mod, A[j + mid + k] = (x - y + mod) % mod;
// else
// A[j + k] = 1ll * Inv2 * (x + y) % mod, A[j + mid + k] = 1ll * Inv2 * (x - y + mod) % mod;
// }
}
}
}
void FWTX(ll *A, ll *B, int n, int t)
{

FWT(A, n, 1, t), FWT(B, n, 1, t);

for (int i = 0; i < n; ++i)
A[i] = 1ll * A[i] * B[i];
FWT(A, n, -1, t);
}
ll a[N], b[N];
char s[N];
int n;
int main()
{
scanf("%d", &n);
n = 1 << n;
scanf("%s", s);
for (int i = 0; i < n; i++)
{
a[i] = s[i] - '0';
a[i] *= 1ll << (1ll * __builtin_popcount(i) << 1);
}
scanf("%s", s);
for (int i = 0; i < n; i++)
{
b[i] = s[i] - '0';
b[i] *= 1ll << (1ll * __builtin_popcount(i) << 1);
}

FWTX(a, b, n, 1);
for (int i = 0; i < n; i++)
{
printf("%lld", (a[i] >> (1ll * __builtin_popcount(i) << 1)) & 3);
}
}