Solution -「ARC 106E」Medals

solution,arc,106e,medals · 浏览次数 : 11

小编点评

```c++ #include #include #include using namespace std; const int N = 18, K = 1e5;int n, k, a[N + 5], f[2 * N * K + 5], g[1 << N];bool check(int upp) { const int LIM = 1 << n, U = LIM - 1; for (int i = 0;i<LIM;++i) g[i] = 0; rep (i,1,upp) g[f[i]]++; for (int j = 0;j<n;++j) for (int i = 0;i<LIM;++i) if (!(i&(1<<j))) g[i|(1<<j)] += g[i]; for (int i = 0;i<LIM;++i) if (upp - g[U^i] < __builtin_popcount(i) * k) return false; return true;} int main(){ ios::sync_with_stdio(0); cin.tie(nullptr); rd(n, k); rds0i(a, n); for (int i = 0;i<n;++i) { for (int t = 0;;t+=2) for (int j = t*a[i]+1;j<(t+1)*a[i]+1;++j) { if (j > 2 * n * k) goto label; f[j] |= 1<<i; } label:; } int l = 0, r = 2 * n * k, res = -1; while (l <= r) { if (int mid = (l + r) / 2; check(mid)) r = mid - 1, res = mid; else l = mid + 1; } cout << res << "\\";} } ```

正文

Desc.

  Link.

  你有 \(n\) 个朋友,他们会来你家玩,第 \(i\) 个人 \(1...A_i\) 天来玩,然后 \(A_i+1...2A_i\) 天不来,然后 \(2A_i+1...3A_i\)
又会来,以此类推;

  每天你会选一个来玩的人,给他颁个奖,如果没人来玩,你就不颁奖。

  你要给每个人都颁 \(K\) 个奖,问至少需要多少天。

Sol.

  前面的部分很套路了,主要看看建出二分图后我们应该做什么。首先根据 Hall's marriage theorem,我们要做的是判断任意子集的邻域大小是否大于等于该子集的大小。把 \(n\) 个人拆成 \(n\times k\) 个点,可以发现进行判断时不需要把同一类点(由同一个工人拆出来的 \(k\) 个点)分开。设 \(f(S)\) 为满足存在集合 \(S\) 中任一工人会来打工的天数,则有解的一个充要条件为 \(\forall S\subseteq 2^{\{1,\dots,n\}},m-f(U\setminus S) \geqslant |S|\times k\)

const int N = 18, K = 1e5;
int n, k, a[N + 5], f[2 * N * K + 5], g[1 << N];
bool check(int upp) {
    const int LIM = 1 << n, U = LIM - 1;
    for (int i=0;i<LIM;++i) g[i] = 0;
    rep (i,1,upp) g[f[i]]++;
    for (int j=0;j<n;++j) for (int i=0;i<LIM;++i) if (!(i&(1<<j))) g[i|(1<<j)] += g[i];
    for (int i=0;i<LIM;++i) if (upp - g[U^i] < __builtin_popcount(i) * k) return false;
    return true;
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(nullptr);
    rd(n, k); rds0i(a, n);
    for (int i=0;i<n;++i) {
        for (int t=0;;t+=2) for (int j=t*a[i]+1;j<(t+1)*a[i]+1;++j) {
            if (j > 2 * n * k) goto label;
            f[j] |= 1<<i;
        }
        label:;
    }
    int l = 0, r = 2 * n * k, res = -1;
    while (l <= r) {
        if (int mid = (l + r) / 2; check(mid)) r = mid - 1, res = mid;
        else l = mid + 1;
    }
    cout << res << "\n";
}

与Solution -「ARC 106E」Medals相似的内容:

Solution -「ARC 106E」Medals

Desc. Link. 你有 \(n\) 个朋友,他们会来你家玩,第 \(i\) 个人 \(1...A_i\) 天来玩,然后 \(A_i+1...2A_i\) 天不来,然后 \(2A_i+1...3A_i\) 又会来,以此类推; 每天你会选一个来玩的人,给他颁个奖,如果没人来玩,你就不颁奖。 你要给

Solution -「HDU」Ridiculous Netizens

Desc. 给定一棵 \(N\) 个节点无根树,找出满足以下条件的集合 \(S\) 的数量: \(S \subseteq \{1,\dots,n\}\); \(S\) 的导出子图联通; \(\displaystyle\prod_{v \in S} a_v \leqslant M\)。 Sol. 点分

Solution -「模拟赛」草莓蛋糕

\(\max(a_x + a_y, b_y + b_x)\) 的贡献形式不是独立的,并不好进行分析。考虑通过分类讨论将 \(\max\) 拆开。若令 \(h_i = a_i - b_i\),\(h'_i = b_i - a_i\),可以发现若 \(h_x \geqslant h'_y\) 取值则为

Solution -「JOISC 2020」建筑装饰 4

朴素的 DP 形式是定义 \(f_{i, j, A/B}\) 表示前 \(i\) 个元素选择了 \(j\) 个 \(A\) 的可达性. \(\mathcal O(n^2)\). 交换状态与值域, 定义 \(f_{i, A/B, A/B}\) 表示前 \(i\) 个元素中的最后一个元素 (即 \(i\

Solution -「LOJ #3310」丁香之路

首先有两个前置技巧:1) 两点间的最短距离就是直接连接两点的边的长度;2) 遍历一个子图的最小花费是最小生成树的边权之和乘二。原问题让我们找出一条最短且必经过钦定边的 \(( s, i )\) 路径,那么我们先将 \(\lang s , i \rang\) 连上,问题就变成了找出一条最短且必经过钦定

MetaTown:一个可以自己构建数字资产的平台

摘要:华为云Solution as Code重磅推出《基于MetaTown构建数字资产平台》解决方案。 本文分享自华为云社区《基于MetaTown构建数字资产平台》,作者: 阿米托福。 华为云Solution as Code重磅推出《基于MetaTown构建数字资产平台》解决方案,由华为云数字资产链

带你了解基于Ploto构建自动驾驶平台

摘要:华为云Solution as Code推出基于Ploto构建自动驾驶平台解决方案。 本文分享自华为云社区《基于Ploto构建自动驾驶平台》,作者:阿米托福 。 2022年6月15日,主题为“因聚而生 为你所能”的华为伙伴暨开发者大会 2022 正式开启,在自动驾驶专场中,华为云携手合作伙伴联合

pbjs 无法编码 bytes 类型数据问题的解决方案

一段包含 bytes 类型的 protobuf 二进制数据,经过 pbjs 解码生成的 json 文件,再传递给 pbjs 编码后生成的二进制数据和原始数据差异巨大,经过一番探究,发现居然是 pbjs 的一个 bug,快来看看你是否踩过这个坑吧~