CF1034E Little C Loves 3 III
CF1034E Little C Loves 3 III
FWT, 构造
子集卷积 + 很小的模数?
但朴素的子集卷积时间空间都过不了
考虑到有个小模数
令 \(A_i = a_i4^{|i|}, B_i= b_i4^{|i|}\)
发现 \(C_k = \sum\limits_{i|j = k} A_iB_j = a_ib_j4^{|i| + |j|}\),这里的 \(|i| + |j| \ge |k|\) ,而题目要求的 \(|i| + |j| = |k|\)
其实 \(c_i = \frac {C_i}{4^{|i|}} \mod 4\)
证明:
因为对于 \(|i| + |j| > |k|\) 的 \(C_k\) , 必定是 \(4^{|k|}\) 的倍数 , 所以除以 \(4^{|k|}\) 就相当于对 \(4\) 取模 , 不影响结果
而对于 \(|i| + |j| = |k|\) 的 \(C_k\) ,除以 \(4^{|k|}\) 就相当于还原
所以对 \(A, B\) 做 FWT ,最终答案除以 \(4^{|i|}\) 就行了
#include <bits/stdc++.h>
#define re register
#define int unsigned long long
// #define pair pair<int, int>
// #define File(a) freopen(a".in", "r", stdin), freopen(a".out", "w", stdout);
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
char buf[1 << 21], *p1 = buf, *p2 = buf;
using namespace std;
inline int read()
{
re int x = 0, f = 0;
re char ch = getchar();
while (!isdigit(ch)) {if (ch == '-') f = 1; ch = getchar();}
while (isdigit(ch)) {x = (x << 3) + (x << 1) + ch - 48; ch = getchar();}
return f ? -x : x;
}
inline string getstr()
{
string res = "";
re char ch = getchar();
while (isspace(ch)) ch = getchar();
while (!isspace(ch)) res.push_back(ch), ch = getchar();
return res;
}
const int N = (1 << 21) + 6, P = 998244353, M = 1e4 + 4;
void FWT(int *A, const int &siz, const int &flag)
{
for (re int len = 1; len < siz; len <<= 1)
{
const int rlen = len << 1;
for (re int i = 0; i < siz; i += rlen)
for (re int j = 0; j < len; ++j)
{
int x = A[i + j], y = A[i + j + len];
A[i + j] = x;
A[i + j + len] = y + x * (flag ? -1ll : 1ll);
}
}
}
int a[N], b[N], mi[N];
#define cnt(i) __builtin_popcount(i)
signed main()
{
int n = read(), siz = 1 << n; mi[0] = 1;
for (re int i = 1; i <= n; ++i) mi[i] = mi[i - 1] * 4ll;
for (re int i = 0; i < siz; ++i) a[i] = (getchar() - 48) * mi[cnt(i)];
getchar();
for (re int i = 0; i < siz; ++i) b[i] = (getchar() - 48) * mi[cnt(i)];
FWT(a, siz, 0), FWT(b, siz, 0);
for (re int i = 0; i < siz; ++i) a[i] = a[i] * b[i];
FWT(a, siz, 1);
for (re int i = 0; i < siz; ++i) printf("%lld", a[i] / mi[cnt(i)] % 4);
return 0;
}

该文不被密码保护。
浙公网安备 33010602011771号