2024ICPC网络赛第二场K
K. Match
位运算逐位考虑!
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define int ll
ll read()
{
ll x = 0; bool f = false; char c = getchar();
while(c < '0' || c > '9') f |= (c == '-'), c = getchar();
while(c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c & 15), c = getchar();
return f ? -x : x;
}
const ll mod = 998244353;
const int N = 205;
int n;
ll K;
vector<ll> a, b;
ll qpow(ll a, ll b, ll mod)
{
ll ans = 1;
while(b)
{
if(b & 1) ans = ans * a % mod;
b >>= 1;
a = a * a % mod;
}
return ans;
}
ll jc[N], inv[N];
void init()
{
jc[0] = jc[1] = inv[0] = inv[1] = 1;
for(int i = 2; i <= 200; ++i) jc[i] = jc[i - 1] * i % mod;
inv[200] = qpow(jc[200], mod - 2, mod);
for(int i = 199; i >= 2; --i) inv[i] = inv[i + 1] * (i + 1) % mod;
}
ll C(int n, int m)
{
if(n < 0 || m < 0 || n < m) return 0;
return jc[n] * inv[m] % mod * inv[n - m] % mod;
}
vector<ll> dfs(vector<ll> &a, vector<ll> &b, int k)
{
vector<ll> c;
if(a.size() == 0 || b.size() == 0) return c;
vector<ll> a0, a1, b0, b1;
for(auto A : a)
if((A >> k) & 1) a1.emplace_back(A);
else a0.emplace_back(A);
for(auto B : b)
if((B >> k) & 1) b1.emplace_back(B);
else b0.emplace_back(B);
if(k == 0)
{
if((K >> k) & 1)
{
int size1 = min(a1.size(), b0.size()), size2 = min(a0.size(), b1.size());
c.resize(size1 + size2);
for(int i = 0; i <= size1; ++i)
for(int j = 0; j <= size2; ++j)
if(i + j - 1 >= 0)
c[i + j - 1] = (c[i + j - 1] + C(a1.size(), i) * C(b0.size(), i) % mod * C(a0.size(), j) % mod * C(b1.size(), j) % mod * jc[i] % mod * jc[j]) % mod;
return c;
}else
{
int size1 = a1.size() + a0.size(), size2 = b0.size() + b1.size(), SIZE = min(size1, size2);
c.resize(SIZE);
for(int i = 1; i <= SIZE; ++i)
c[i - 1] = (c[i - 1] + C(size1, i) * C(size2, i) % mod * jc[i]) % mod;
return c;
}
}
if((K >> k) & 1)
{
vector<ll> tmp1 = dfs(a0, b1, k - 1), tmp2 = dfs(a1, b0, k - 1);
int size1 = tmp1.size(), size2 = tmp2.size();
c.resize(size1 + size2);
for(int i = 0; i <= size1; ++i)
for(int j = 0; j <= size2; ++j)
if(i + j > 0)
c[i + j - 1] = (c[i + j - 1] + (i > 0 ? tmp1[i - 1] : 1ll) * (j > 0 ? tmp2[j - 1] : 1ll)) % mod;
return c;
}else
{
vector<ll> tmp1 = dfs(a0, b0, k - 1), tmp2 = dfs(a1, b1, k - 1);
int size1 = tmp1.size(), size2 = tmp2.size();
int size3 = min(a0.size(), b1.size()), size4 = min(a1.size(), b0.size());
int sizea0 = a0.size(), sizea1 = a1.size(), sizeb0 = b0.size(), sizeb1 = b1.size();
c.resize(size1 + size2 + size3 + size4);
for(int i = 0; i <= size1; ++i)
for(int j = 0; j <= size2; ++j)
for(int k = min(sizea0 - i, sizeb1 - j); k >= 0; --k)
for(int t = min(sizea1 - j, sizeb0 - i); t >= 0; --t)
if(i + j + k + t > 0)
c[i + j + k + t - 1] = (c[i + j + k + t - 1] + (i > 0 ? tmp1[i - 1] : 1ll) * (j > 0 ? tmp2[j - 1] : 1ll) % mod * C(sizea0 - i, k) % mod * C(sizea1 - j, t) % mod * C(sizeb0 - i, t) % mod * C(sizeb1 - j, k) % mod * jc[k] % mod * jc[t]) % mod;
while(c.size() && (*--c.end()) == 0) c.pop_back();
return c;
}
}
signed main()
{
init();
n = read(), K = read();
a.resize(n), b.resize(n);
for(int i = 1; i <= n; ++i) a[i - 1] = read();
for(int i = 1; i <= n; ++i) b[i - 1] = read();
vector<ll> c = dfs(a, b, 59);
for(int i = 0; i < c.size(); ++i) printf("%lld\n", c[i]);
int m = n - c.size();
for(int i = 1; i <= m; ++i) printf("0\n");
return 0;
}
/*
4 40
24 72 49 26
88 6 32 2
10
29
24
4
*/