首页 > 其他分享 >[USACO18DEC] Cowpatibility G

[USACO18DEC] Cowpatibility G

时间:2025-01-02 20:30:22浏览次数:1  
标签:hash Cowpatibility int ret rm USACO18DEC 奶牛 omega

前言

想想自己做, 一共就两种 \(\rm{trick}\) 还不会?

思路

你发现两个不能和谐共处的奶牛, 当且仅当他们的 \(10\) 个喜好不重
因为要求时间复杂度不能是 \(\mathcal{O} (n^2)\) , 所以肯定要想办法做到不枚举点对

这个时候联想到之前的一道题 [CEOI2010 day2] pin, 我们考虑利用相似的方法 (结果之前那题是水过去的, 又去研究了一遍花费 \(10 \ \rm{min}\))

我们考虑「钦定」当前这只奶牛的 \(k\) 个喜好与其他奶牛相同, 这个时候我们可以轻松的 \(\mathcal{O}(1)\) 统计出有多少只, 仅仅需要使用 \(\rm{hash}\)
其中统计的总时间复杂度是 \(\mathcal{O} (2^{\omega} n)\) , 其中 \(\omega = 5\)

这不无敌了, 你发现令 \(f(k)\) 为「至多」\(k\) 个喜好与其他奶牛不同的对数, 可以快速计算出来 (即「钦定」\(\omega - k\) 个位置相同), 套路的, 令 \(g(k)\) 为「恰好」\(k\) 个喜好与其他奶牛不同的对数

\[f(k) = \sum_{i = 0}^{k} {\omega - i \choose \omega - k} g(i) \iff g(k) = \sum_{i = 0}^{k} (-1)^{k - i} {\omega - i \choose \omega - k} f(i) \]

容易发现

\[ans \gets g(\omega) = \sum_{i = 0}^{\omega} (-1)^{i + 1} f(i) \]

实现

\(\rm{TJ}\) 区并没有这种做法, 只能自己多考虑一下打出来了

框架

首先是计算 \(f\)
我们需要在枚举的过程中, 用二进制枚举的方式处理相同的喜好集合, 然后统计进 \(\rm{hash}\)

6, 注意到不能用 \(\rm{vector}\) , 而应该使用 \(\rm{set}\)

代码

#include <bits/stdc++.h>
#define int long long
const int MAXN = 5e4 + 20;

int n;
int cows[MAXN][5];

std::map<std::set<int>, int> hash; // 映射 hash

int f[6];
/*计算 f(i)*/
void fcalc() {
    for (int i = 1; i <= n; i++) for (int s = 0; s < 32; s++) { // 枚举位置 / 状态
        std::set<int> ret; ret.clear(); for (int j = 0; j < 5; j++) if ((s >> j) & 1) ret.insert(cows[i][j]);
        f[5 - __builtin_popcount(s)] += hash[ret]; hash[ret]++;
    }
}

signed main()
{
    scanf("%lld", &n);
    for (int i = 1; i <= n; i++) for (int j = 0; j < 5; j++) scanf("%lld", &cows[i][j]);

    fcalc();
    int ans = 0;
    for (int i = 0; i <= 5; i++) {
        ans += (i % 2 ? 1ll : -1ll) * f[i];
    }
    printf("%lld", ans);

    return 0;
}

总结

很像啊, 基本上逻辑相通

也算是常见 \(\rm{trick}\) , 本质上是观察到用 \(\rm{hash}\) 计算对数可以做到更快, 而且只有 \(\omega = 5\) 方便处理子集

标签:hash,Cowpatibility,int,ret,rm,USACO18DEC,奶牛,omega
From: https://www.cnblogs.com/YzaCsp/p/18648699

相关文章

  • P5155 [USACO18DEC] Balance Beam P
    假设有一个长度为\(L\)的木块。定义\(f_i\)从\(i\)走到\(L\)的概率,有\(f_i=\dfrac{f_{i+1}+f_{i-1}}{2}\)。由\(f_1=0,f_L=1\)可以递推得出\(f_i=\dfrac{i}{L}\)。若一个节点移动的期望收益比当前点停止的收益低,则设这个点为关键点。从\(i\)出发开始移动,期望收益......
  • P5156 [USACO18DEC] Sort It Out P 题解
    题意有一个长度为\(n\)的排列\(a_1,a_2,\cdots,a_n\),选出\(\{1,2,\cdots,n\}\)的一个子集,对这个子集中的数依次进行如下操作:设当前数为\(v\),则若\(a_v\)大于\(a_{v+1}\)(如果有的话),就交换。如果小于,则若\(a_v<a_{v-1}\)(如果有的话),就交换。重复上述操作知道\(a_{v-1}<......
  • [USACO18DEC]Balance Beam P
    [USACO18DEC]BalanceBeamP热爱卡精度的你,为什么分数不取模?既然不去模,那么拿到这个题先想想能不能乱搞过去。设\(f_{i,j}\)表示\(i\)点出发至多走\(j\)次的最优期望报酬。当\(j\rightarrow+\infty\)时视为答案。转移为\[f_{i,j}=\max\{f_{i,j-1},\frac{f_{i......