题面

K.Match

给定长度为 \(n\) 的两个序列 \(a\) 和 \(b\),当且仅当 \(a_i ⊕ b_j ≥ k\) 时,\(a_i\) 与 \(b_j\) 连一条双向边,其中 \(⊕\) 表示 XOR 运算。对于 \([1, n]\) 范围内的每个 \(x\),计算大小为 \(x\) 的匹配数的个数,结果对 \(998244353\) 取模。


题解

考虑两个序列 \(A, B\) 如何计算,不妨考虑从 \(k\) 的最高位开始枚举,对于 \(k\) 的下一个位,当前的合法 \(A, B\) 一定,我们为了方便讨论,按当前位为 \(0/1\) 分为 \(A_0, A_1, B_0, B_1\)。

序列 \(A_0, A_1, B_0, B_1\) 的大小是单调不增的,为了方便讨论,我们规定 \(|S|\) 表示集合 \(S\) 的大小,\(\leftrightarrow\) 表示两者有边。

  • \(k\) 的下一位为 \(1\),序列 \(A, B\) 合法的条件是 \(A_0 \leftrightarrow B_1\) 和 \(A_1 \leftrightarrow B_0\)。

    • 记 \(A_0 \leftrightarrow B_1\) 的方案数为 \(f_i\),\(A_1 \leftrightarrow B_0\) 的方案数为 \(g_i\),容易发现,答案为 \(f\) 与 \(g\) 的一个卷积,即 \(ans_{i + j} = f_i \times g_j\)。
  • \(k\) 的下一位为 \(0\),序列 \(A, B\) 的合法条件为 \(A_0 \leftrightarrow B_0\) 和 \(A_1 \leftrightarrow B_1\),同时对于 \(A_0 \leftrightarrow B_1\) 和 \(A_1 \leftrightarrow B_0\) 一定成立,我们需要考虑如何将两者答案合并。

    • 记 \(A_0 \leftrightarrow B_0\) 的方案数为 \(f_i\),\(A_1 \leftrightarrow B_1\) 的方案数为 \(g_i\),\(A_0 \leftrightarrow B_1\) 的方案数为 \(h_i\),\(A_1 \leftrightarrow B_0\) 的方案数为 \(t_i\)。

      • 考虑 \(A_0 \leftrightarrow B_1\) 和 \(A_1 \leftrightarrow B_0\) 的任选性,任选 \(i\) 个对其随机排列,容易看出 \(h_i = i!\binom{|A_0|}{i}\binom{|B_1|}{i}\),\(t_i = i!\binom{|A_1|}{i}\binom{|B_0|}{i}\)。

      • \(A_0 \leftrightarrow B_0\) 和 \(A_1 \leftrightarrow B_1\) 的组合意义同 \(k\) 取 \(1\) 时的操作,对 \(f\) 与 \(g\) 做卷积得到 \(S_{i+j} = f_i \times g_j\)。

    • 为了将 \(h, t\) 与 \(S\) 合并,枚举三个集合分别选择了 \(i, j, l\) 个匹配。

      • 对每组 \((i, j)\),去除 \(A_0 \leftrightarrow B_0\) 使用的 \(i\) 对,\(A_1 \leftrightarrow B_1\) 使用的 \(j\) 对,每次重新计算一组 \(S\),其中 \(h_u = u!\binom{|A_0| - i}{u}\binom{|B_1| - j}{u}\),\(t_u = u!\binom{|A_1| - j}{u}\binom{|B_0| - i}{u}\)

      • 先卷 \(h\) 和 \(t\) 得到 \(S\),再把三者卷起来有 \(ans_{i + j + l} = h_i \times t_j \times S_l\)。

  • 考虑边界情况,定义 \(\operatorname{solve(A, B, lev)}\) 为递归计算的 \(A, B\) 序列,\(lev\) 为当前考虑的位。

    • 当 \(|A| = 0\) 或 \(|B| = 0\) 时,没有可选项数,\(ans_0 = 1\),\(ans_i = 0(i > 0)\)。

    • 当 \(lev = -1\) 时,说明前面的位被考虑完毕了,\(A, B\) 可以任意组合,计算 \(ans_i = i!\binom{|A|}{i}\binom{|B|}{i}\)。

    • 否则将 \(A, B\) 按当前位分解为 \(A_0, A_1, B_0, B_1\) 对下一个 \(lev\) 讨论。

按照题意分析复杂度,对于 \(k\) 的位为 \(0\) 时,计算一次 \(S\) 的复杂度是卷积 \(O(n^2)\) 的,卷一次 \(ans_{i + j + l}\) 需要枚举 \(i, j\),并在当前 \(i, j\) 下卷出一个 \(S\),时间复杂度是 \(O(n^4)\) 的,可以优化做到 \(O(n^3\log{n})\),但是原算法时间复杂度很小,因为 \(|A|, |B|\) 的大小是单调不增的,所以跑不满。

总体时间复杂度 \(O(n^4\log{k})\),代码如下。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<ll> Poly;
const int N = 405, mod = 998244353, maxn = 400;
ll n, k;
ll frac[N], inv[N]; ll ksm(ll a, ll k)
{
ll res = 1;
while (k)
{
if (k & 1) res = res * a % mod;
k >>= 1;
a = a * a % mod;
}
return res;
} void init()
{
frac[0] = inv[0] = 1;
for (int i = 1; i <= maxn; i ++ ) frac[i] = frac[i - 1] * i % mod;
inv[maxn] = ksm(frac[maxn], mod - 2);
for (int i = maxn - 1; i; i -- ) inv[i] = inv[i + 1] * (i + 1) % mod;
} ll C(ll x, ll y)
{
if (x < y || y < 0) return 0;
return frac[x] * inv[y] % mod * inv[x - y] % mod;
} Poly Covolution(Poly x, Poly y)
{
Poly tmp(x.size() + y.size() - 1);
for (int i = 0; i < x.size(); i ++ )
for (int j = 0; j < y.size(); j ++ )
(tmp[i + j] += x[i] * y[j]) %= mod;
return tmp;
} Poly calc(int x, int y)
{
Poly tmp(min(x, y) + 1);
for (int i = 0; i <= min(x, y); i ++ ) tmp[i] = C(x, i) * C(y, i) % mod * frac[i] % mod;
return tmp;
} Poly solve(Poly x, Poly y, int lev)
{
if (x.empty() || y.empty()) return Poly(1, 1);
if (lev == -1) return calc(x.size(), y.size());
Poly X[2], Y[2];
for (auto i : x) X[i >> lev & 1].push_back(i);
for (auto i : y) Y[i >> lev & 1].push_back(i);
if (k >> lev & 1) return Covolution(solve(X[1], Y[0], lev - 1), solve(X[0], Y[1], lev - 1));
Poly tmp[2], res(min(x.size(), y.size()) + 1);
tmp[0] = solve(X[0], Y[0], lev - 1), tmp[1] = solve(X[1], Y[1], lev - 1);
for (int i = 0; i < tmp[0].size(); i ++ )
for (int j = 0; j < tmp[1].size(); j ++ )
{
Poly c = Covolution(calc(X[0].size() - i, Y[1].size() - j), calc(X[1].size() - j, Y[0].size() - i));
for (int l = 0; l < c.size(); l ++ ) (res[i + j + l] += tmp[0][i] * tmp[1][j] % mod * c[l]) %= mod;
}
return res;
} int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
init();
cin >> n >> k;
Poly a(n), b(n);
for (int i = 0; i < n; i ++ ) cin >> a[i];
for (int i = 0; i < n; i ++ ) cin >> b[i];
Poly ans = solve(a, b, 60);
ans.resize(n + 1);
for (int i = 1; i <= n; i ++ ) cout << ans[i] << "\n";
return 0;
}

The 2024 ICPC Asia East Continent Online Contest (II) K.Match的更多相关文章

  1. 训练20191009 2018-2019 ACM-ICPC, Asia East Continent Finals

    2018-2019 ACM-ICPC, Asia East Continent Finals 总体情况 本次训练共3小时20分钟,通过题数4. 解题报告 D. Deja vu of - Go Play ...

  2. 2018-2019 ACM-ICPC, Asia East Continent Finals I. Misunderstood … Missing(dp)

    题目链接: http://codeforces.com/gym/102056/problem/I 题意: 人物有l两个属性分别是$A,D$ 每个回合人物$A\pm D$ 每个回合有三个选择分别是: 1 ...

  3. 2018-2019 ACM-ICPC, Asia East Continent Finals部分题解

    C:显然每p2个数会有一个0循环,其中22 32 52 72的循环会在200个数中出现,找到p2循环的位置就可以知道首位在模p2意义下是多少,并且循环位置几乎是唯一的(对72不满足但可能的位置也很少) ...

  4. 2018-2019 ACM-ICPC, Asia East Continent Finals Solution

    D. Deja vu of … Go Players 签. #include <bits/stdc++.h> using namespace std; int t, n, m; int m ...

  5. 2017-2018 ACM-ICPC Asia East Continent League Final (ECL-Final 2017) Solution

    A:Chat Group 题意:给出一个n, k 计算C(n, k) -> C(n,n) 的和 思路:k只有1e5 反过来想,用总的(2^ n) 减去 C(n, 0) -> C(n, k ...

  6. The 2017 ACM-ICPC Asia East Continent League Final记录

    首先感谢tyz学弟的麻麻-给我们弄到了名额- 然后就开始了ACM ECLFinal的玩耍,A*仙人掌可是立了flag要好好打的- 试机赛好像就全是GCJ kickstart的原题,然后AK了但是由于一 ...

  7. Codeforces Gym 101775D Mr. Panda and Geometric Sequence(2017-2018 ACM-ICPC Asia East Continent League Final,D题,枚举剪枝)

    题目链接  ECL-Final 2017 Problem D 题意  给定$2*10^{5}$组询问,每个询问求$l$到$r$之间有多少个符合条件的数 如果一个数小于等于$10^{15}$, 并且能被 ...

  8. 2019-2020 ICPC Asia Hong Kong Regional Contest

    题解: https://files.cnblogs.com/files/clrs97/19HKEditorial-V1.zip Code:(Part) A. Axis of Symmetry #inc ...

  9. 2018-2019 ACM-ICPC, Asia East Continent Final L Eventual … Journey

    #include<iostream> using namespace std; ; int cnt[MAX]; int ans[MAX]; int a[MAX]; int main() { ...

  10. 训练20191005 2017-2018 ACM-ICPC Asia East Continent League Final

    A 签到 M 签到 K 读懂后签到 L 博弈论 [引理]出现SXXS结构时后手必胜. 很容易发现n为奇数时后手不可能胜利,n为偶数时先手不可能胜利.n≤6时一定平局,n≥7时先手有可能胜利,n≥16时 ...

随机推荐

  1. 线性dp:LeetCode674. 最长连续递增序列

    LeetCode674. 最长连续递增序列 阅读本文之前,需要先了解"动态规划方法论",这在我的文章以前有讲过 链接:动态规划方法论 本文之前也讲过一篇文章:最长递增子序列,这道题 ...

  2. LaTeX 编译中文文档

    介绍 LaTeX 原生不支持中文.为了添加中文的功能,我们需要引入宏包.XeLaTeX 原生支持中文.不过由于默认使用的字体是英文字体,我们需要设置中文字体之后才能用.不过由于一些原因,在使用 LaT ...

  3. 一场 Kafka CRC 异常引发的血案

    一.问题概述 客户的生产环境突然在近期间歇式的收到了Kafka CRC的相关异常,异常内容如下 Record batch for partition skywalking-traces-0 at of ...

  4. springCloud allibaba 微服务引言

    微服务篇: springcloud 常见组件有哪些 nacos 的服务注册表结构是怎样的 nacos 如何支撑阿里内部数十万服务注册压力 nacos 如何避免并发读写冲突问题 nacos 和eurek ...

  5. 画流程图、状态图、时序图、甘特图的JS库-mermaid-js

    参考地址:https://github.com/mermaid-js/mermaid 原生使用方式: <!DOCTYPE html> <html> <head> & ...

  6. HEDGE: 通过特征交互检测生成文本分类的层次解释《Generating Hierarchical Explanations on Text Classification via Feature Interaction Detection》(LIME算法、神经网络预测的分层解释CD和ACD、Shapley Value夏普利值、Leave-One-Out留一法、HEDGE)

    先来吐个槽:啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊,为什么我的导师又嫌我PPT做的很烂,( Ĭ ^ Ĭ ) 论文:Generating Hierarchical Explanations on Text Cl ...

  7. Facebook – Pixel

    介绍 Facebook 的 Pixel 类似于 Google 的 Analytics. 作用是 tracking 流量进入网站后是否转化. 这样就可以持续优化广告效果. 参考 Facebook Doc ...

  8. JavaScript – 基本语法

    参考 阮一峰 – 基本语法 Switch switch 经常用来取代 else if, 因为可读性比价高, 而且通常性能也比较好. standard 长这样 const orderStatus = ' ...

  9. ASP.NET Core Library – FluentValidation

    前言 之前就有写过学习笔记: Asp.net core 学习笔记 Fluent Validation 但都是用一点记入一点,零零散散不好读, 这一篇来稍微整理一下. 主要参考: Fluent Vali ...

  10. 图解MQTT概念、mosquitto编译和部署 ,写代码,分别使用外网和本地服务器进行测试

    前沿提要: MQTT是什么不知道? 看这一篇:https://www.cnblogs.com/happybirthdaytoyou/p/10362336.html 阿里云官网玩不转? 看这一篇: ht ...