牛客练习赛105

练习赛105

A 切蛋糕的贝贝

题目描述

贝贝有一块正 n 边形的蛋糕,他想将其分为 6 块,使得面积之比为1:1:4:5:1:4 (顺序可以打乱)。每一刀存在以下两种切法:
1. 切线为经过多边形的重心(其外接圆的圆心)的对角线
2. 切线为多边形的重心与其顶点的连线
贝贝想知道最少需要的刀数,但是他是个菜狗,以至于他无法解决这个问题,所以他找到了一个大佬(也就是你)帮忙解决。

思路

只有 n 能够被 1+1+4+5+1+4 整除时才会有答案。

int x; std::cin >> x; std::cout << (x % 16 ? -1 : x / 16 * 5) << "\n";

B 抱歉,这没有集美

题目描述

n 个学生编号为 1n ,现在分给他们每一人一个按 1n 编号的球,第 i 个学生分到的球得编号为 pi ,如果存在有学生自己得编号和手中得球得编号的最大公约数 gcd(i,pi) 为偶数,就是一个好的分法。现在问有多少种好的分法。

思路:

如果正向去考虑有多少种分法的话,需要从 n2 个偶数种选出来 1 个来安放在所有的偶数的位置上的方案,也就是 (n21)(n21)An1n1 但是这样的算法的话会有重复的选法被记录进去,所以正向很难算出来。那么就考虑正难则反的方法,让所有的奇数都占据在偶数的位置上,那么就是 An2n2An2n2 ,所以最终的答案就是用总共的 Ann 减去这个值就行了。注意用逆元去计算

CNM::init(); int n; std::cin >> n; int t = n / 2 + (n & 1); std::cout << CNM::fac[n] - CNM::fac[t] * CNM::fac[t] << "\n";

C 打牌的贝贝

题目描述:

贝贝和宁宁玩一种卡牌游戏,一共有 2n 张牌,每个数介于 12n 之间且各不相同,每个人一开始分别有 n 张牌。规则是:贝贝先出一张牌,宁宁要出一张比贝贝所给出的牌点数大的牌,不然宁宁输;如果最后所有的牌都出完了就是贝贝输。求两人获胜的方案有多少种。

思路:

因为贝贝每出一张牌宁宁都要出一张比这个数大的牌,所以相当于一个匹配的问题,把贝贝出的牌看作左括号,宁宁出的牌看作右括号,如果最终是一个合法的括号序列,就是宁宁赢否则贝贝赢。而合法括号序列数可以用卡特兰数 CatalannO(n) 的时间复杂度下计算得出。

void solve() { int n; std::cin >> n; Z ans = binom(2 * n, n) * Z(n + 1).inv() * power(Z(1), n); std::cout << binom(2 * n, n) - ans << " " << ans << "\n"; }

卡特兰数计算的公式:

Hn=(2nn)(2nn1)

Hn=Hn1(4n2)n+1

Hn=(2nn)knn+1,(k)

D 点分治分点

题目描述:

给定一个 n 个点, m 条带权的边的有向图,定义一条简单路径的 low 值为其路径上的边权的最小值,d(u,v) 为从 uv 所有简单路径的最大 low 值。注意,简单路径不能包含两个相同的点,故恒有 d(u,u)=1 .
对于给定的 su1n 输出 d(s,u) ,如果没有任何一条简单路径则输出 1

思路:

首先观察到是有向图上求两点之间路径上边权最小化的最大值,Kruskal 重构树就用不上了。考虑到直接统计从 sx 点的答案,不太好更新状态,所以也不能直接从起点开始遍历,那么就考虑用最小生成树的思想 ,按照边权从大到小的顺序来枚举所有的边,看这条边是不是与 s 所在的集合相连,是的话就保留这一条边,否则删去它;这样就保证了在最后剩余的边,就是我们想要得到的答案。

int n, m, s; std::cin>> n >> m >> s; std::vector<std::vector<std::array<int, 2>>> adj(n + 1); for (int i = 1; i <= m; i++) { int u, v, w; std::cin >> u >> v >> w; adj[u].push_back({v, w}); } vector<int> dist(n + 1); auto dijkstra = [&]() { std::vector<bool> vis(n + 1); dist[s] = 1 << 30; priority_queue<pair<int, int>> heap; heap.push(make_pair(dist[s], s)); while (heap.size()) { std::pair<int, int> t = heap.top();heap.pop(); int ver = t.second, distance = t.first; if (vis[ver]) continue; vis[ver] = true; for (auto& G : adj[ver]) { int v = G[0], w = G[1]; if (dist[v] < std::min(dist[ver], w)) //更新low值 dist[v] = std::min(dist[ver], w), heap.push(make_pair(dist[v], v)); } } }; dijkstra(); for (int i = 1; i <= n; i++) { if (i == s || dist[i] == 0) dist[i] = -1; std::cout << dist[i] << " "; }

__EOF__

本文作者HoneyGrey
本文链接https://www.cnblogs.com/Haven-/p/16861581.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   浅渊  阅读(41)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示