【牛客小白月赛69】题解与分析A-F【蛋挞】【玩具】【开题顺序】【旅游】【等腰三角形(easy)】【等腰三角形(hard)】
比赛传送门:https://ac.nowcoder.com/acm/contest/52441
感觉整体难度有点偏大。
作者:Eriktse
简介:19岁,211计算机在读,现役ACM银牌选手力争以通俗易懂的方式讲解算法!️欢迎关注我,一起交流C++/Python算法。(优质好文持续更新中……)
个人博客:www.eriktse.com
A-蛋挞
签到题。
只需比较a / b和a % b的大小即可。注意开longlong。
#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main()
{
int a, b;scanf("%lld %lld", &a, &b);
if(a / b < a % b)printf("niuniu eats more than others");
else if(a / b > a % b)printf("niuniu eats less than others");
else printf("same");
return 0;
}
B-玩具
排序贪心。
因为我们要将n个玩具全部买下,所以我们免单的玩具价格越高越好,我们将整个数组排升序后从后往前两个两个拿,且只付更高价格的玩具的钱。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 1e6 + 9;
int a[maxn];
signed main()
{
int n;scanf("%lld", &n);
for(int i = 1;i <= n; ++ i)scanf("%lld", a + i);
sort(a + 1,a + 1 + n);
int ans = 0;
for(int i = n;i >= 1; -- i)
{
ans += a[i];
i --;
}
printf("%lld\n", ans);
return 0;
}
C-开题顺序
dfs。
题目数量比较小,我们可以枚举出所有的开题顺序,然后计算出最终分数取大即可,注意剪枝,当时间超过t的时候可以直接结束,此时的分数已经无效了。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 15;
int a[maxn], b[maxn], c[maxn], x[maxn], y[maxn];
int n, t, p;
bitset<maxn> vis;
//当前正在选第dep道题
int dfs(int dep, int ti, int sc)
{
if(ti > t)return 0;//当累计做题时间已经超过了t说明比较已经结束了
if(dep == n + 1)return sc;
int res = sc;
for(int i = 1;i <= n; ++ i)
{
if(vis[i])continue;
//切了第i道题
ti += x[i];
vis[i] = true;
res = max(res, dfs(dep + 1, ti, sc + max(c[i], a[i] - ti * b[i] - y[i] * p)));
vis[i] = false;
ti -= x[i];
}
return res;
}
signed main()
{
scanf("%lld %lld %lld", &n, &t, &p);
for(int i = 1;i <= n; ++ i)
scanf("%lld %lld %lld %lld %lld", a + i, b + i, c + i, x + i, y + i);
printf("%lld\n", dfs(1, 0, 0));
return 0;
}
D-旅游
最小生成树(并查集) + 二分。
首先我们知道要使得所有点互联,且边权尽可能小,应该建立一棵最小生成树,然后修复树中所有的边即可。
然后国家帮忙修复边权<=p的部分,那么我们可以想到,当p较大时,牛牛的资金肯定可以足够修复剩下的,当p较小时,牛牛要修的路就比较多,就修不了。
所以“y=牛牛能否修复剩下的路”是随着p单调的,当p大时,y=1,当p小时,y=0,我们要做的就是找到那个交界处,二分即可。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 1e5 + 9;
map<int, int> mp[maxn];
struct Edge
{
int x, y, w;
};
int pre[maxn];
//路径压缩的并查集
int root(int x){return pre[x] = (pre[x] == x ? x : root(pre[x]));}
int a[maxn];//a里面存放最小生成树的所有边权
int n, m, c, cnt;
bool check(int k)
{
int res = 0;//贪心求最小代价,数组逆序点乘
for(int i = cnt, j = 0;i >= 1; -- i)
{
if(a[i] <= k)break;//<=k的部分国家买单不用考虑了
res += (++ j) * a[i];
}
return res <= c;
}
signed main()
{
scanf("%lld %lld %lld", &n, &m, &c);
/*最小生成树,共3步*/
vector<Edge> vec;
//1.存边
for(int i = 1;i <= m; ++ i)
{
int x, y, w;scanf("%lld %lld %lld", &x, &y, &w);
vec.push_back({x, y, w});//将边存入vec中
}
//2.将边升序
sort(vec.begin(), vec.end(), [](const Edge &u, const Edge &v)
{
return u.w < v.w;
});
//3.贪心建树,并查集判断连通性
for(int i = 1;i <= n; ++ i)pre[i] = i;//并查集初始化
for(auto &i : vec)
{
int x = i.x, y = i.y, w = i.w;
if(root(x) == root(y))continue;
a[++ cnt] = w;//a自然是升序的
pre[root(x)] = root(y);
}
/*生成树结束*/
//以下为二分部分
int l = -1, r = 2e9;
while(l + 1 != r)
{
int mid = (l + r) >> 1;
if(check(mid))r = mid;
else l = mid;
}
printf("%lld\n", r);
return 0;
}
E-等腰三角形(easy)
暴力枚举。
枚举出所有三个点组成的三元组,注意不要重复。
可以通过海伦公式来求面积判断是否共线。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 500;
const double eps = 1e-6;
struct Point
{
int x, y;
}p[maxn];
int dist(const Point &u, const Point &v)
{
int dx = u.x - v.x;
int dy = u.y - v.y;
return dx * dx + dy * dy;
}
double area(double a, double b, double c)
{
double p = (a + b + c) / 2.0;
return sqrt(p * (p - a) * (p - b) * (p - c));
}
signed main()
{
int n;scanf("%lld", &n);
for(int i = 1;i <= n; ++ i)
scanf("%lld %lld", &p[i].x, &p[i].y);
int ans = 0;
for(int i = 1;i <= n; ++ i)
{
for(int j = i + 1;j <= n; ++ j)
{
for(int k = j + 1;k <= n; ++ k)
{
int d1 = dist(p[i], p[j]);
int d2 = dist(p[i], p[k]);
int d3 = dist(p[j], p[k]);
if(area(sqrt(d1), sqrt(d2), sqrt(d3)) <= eps)continue;
if(d1 == d2 || d1 == d3 || d2 == d3)ans ++;
}
}
}
printf("%lld\n", ans);
return 0;
}
F-等腰三角形(hard)
这题肯定不能暴力枚举了。
我们可以发现,以整数点作为定点肯定无法构成等边三角形。
假如我们要构成一个等边三角形,那么就需要有60度的角,假如这个60度的角由两个角x,y相加而成,就有:
$$ tan60\degree = tan(x+y)= \frac{tanx + tany}{1-tanx \times tany}$$
其中tan60是一个无理数,但是后面的tanx, tany都是有理数,一个无理数无法通过有理数的加减乘除算出,所以在整数点中构造不出60度的角。

我们枚举每一个点A,然后枚举其他点作为B,然后再查一下有多少C即可(也就是和A距离等于dist(AB)的点),这里只需保证C的下标小于B的下标,就保证了一个偏序关系,就不会重复计算。
接下来需要将“三点共线”的这样“特殊等腰三角形”减去,我们只需计算有多少这样的“线段”即可。

枚举每一个点A,再查一下A'是否存在即可,可以对点做一个桶来判断,因为地图并不大。
#include <bits/stdc++.h>
#include <bits/extc++.h>
#define int long long
using namespace std;
const int maxn = 3009, T = 1000;
const double eps = 1e-6;
struct Point
{
int x, y;
}p[maxn];
int dist(const Point &u, const Point &v)
{
int dx = u.x - v.x;
int dy = u.y - v.y;
return dx * dx + dy * dy;
}
int cnt[2123456];
bitset<2005> vis[2005];
signed main()
{
int n;scanf("%lld", &n);
for(int i = 1;i <= n; ++ i)
{
scanf("%lld %lld", &p[i].x, &p[i].y);
vis[p[i].x + T][p[i].y + T] = true;
}
int ans = 0;
for(int i = 1;i <= n; ++ i)
{
for(int j = 1;j <= n; ++ j)
{
if(i == j)continue;
ans += (cnt[dist(p[i], p[j])] ++);
}
for(int j = 1;j <= n; ++ j)
{
if(i == j)continue;
cnt[dist(p[i], p[j])] = 0;
}
}
int cnt = 0;
for(int i = 1;i <= n; ++ i)
{
for(int j = 1;j <= n; ++ j)
{
if(i == j)continue;
int tx = 2 * p[j].x - p[i].x;
int ty = 2 * p[j].y - p[i].y;
if(tx < -500 || tx > 500 || ty < -500 || ty > 500)continue;
if(vis[tx + T][ty + T])cnt ++;
}
}
printf("%lld\n", ans - cnt / 2);
return 0;
}
本文由eriktse原创,创作不易,如果对您有帮助,欢迎小伙伴们点赞、收藏、留言
【牛客小白月赛69】题解与分析A-F【蛋挞】【玩具】【开题顺序】【旅游】【等腰三角形(easy)】【等腰三角形(hard)】的更多相关文章
- 树的最长链-POJ 1985 树的直径(最长链)+牛客小白月赛6-桃花
求树直径的方法在此转载一下大佬们的分析: 可以随便选择一个点开始进行bfs或者dfs,从而找到离该点最远的那个点(可以证明,离树上任意一点最远的点一定是树的某条直径的两端点之一:树的直径:树上的最长简 ...
- 【牛客小白月赛21】NC201605 Bits
[牛客小白月赛21]NC201605 Bits 题目链接 题目描述 Nancy喜欢做游戏! 汉诺塔是一个神奇的游戏,神奇在哪里呢? 给出3根柱子,最开始时n个盘子按照大小被置于最左的柱子. 如果盘子数 ...
- 牛客小白月赛16 小石的妹子 二分 or 线段树
牛客小白月赛16 这个题目我AC之后看了一下别人的题解,基本上都是线段树,不过二分也可以. 这个题目很自然就肯定要对其中一个进行排序,排完序之后再处理另外一边,另一边记得离散化. 怎么处理呢,你仔细想 ...
- 牛客网 牛客小白月赛5 I.区间 (interval)-线段树 or 差分数组?
牛客小白月赛5 I.区间 (interval) 休闲的时候写的,但是写的心情有点挫,都是完全版线段树,我的一个队友直接就水过去了,为啥我的就超内存呢??? 试了一晚上,找出来了,多初始化了add标记数 ...
- 牛客小白月赛8 - E - 诡异数字 数位DP
牛客小白月赛8 - E - 诡异数字 题意: 求区间中,满足限制条件的数字的个数. 限制条件就是某些数字不能连续出现几次. 思路: 比较裸的数位DP, DP数组开一个dp[len][x][cnt] 表 ...
- 牛客小白月赛18 Forsaken给学生分组
牛客小白月赛18 Forsaken给学生分组 Forsaken给学生分组 链接:https://ac.nowcoder.com/acm/contest/1221/C来源:牛客网 Forsaken有 ...
- 牛客小白月赛18 Forsaken喜欢数论
牛客小白月赛18 Forsaken喜欢数论 题目传送门直接点标题 Forsaken有一个有趣的数论函数.对于任意一个数xxx,f(x)f(x)f(x)会返回xxx的最小质因子.如果这个数没有最小质 ...
- 牛客小白月赛19 E 「火」烈火燎原 (思维,树)
牛客小白月赛19 E 「火」烈火燎原 (思维,树) 链接:https://ac.nowcoder.com/acm/contest/2272/E来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空 ...
- 【牛客小白月赛21】NC201604 Audio
[牛客小白月赛21]NC201604 Audio 题目链接 题目大意: 给出三点 ,求到三点距离相等的点 的坐标. 解析 考点:计算几何基础. 初中蒟蒻表示不会什么法向量.高斯消元..qwq 方法一: ...
- 牛客小白月赛65ABCD(E)
比赛链接:牛客小白月赛65_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ (nowcoder.com) A:牛牛去购物 题意 ...
随机推荐
- not eligible for getting processed by all BeanPostProcessors
描述 这个BUG大的起源是我上线以后,在后台看日志的时候发现一行奇怪的INFO日志: 2022-06-09 23:34:24 [restartedMain] [org.springframework. ...
- token能放在cookie中吗
能. token一般是用来判断用户是否登录的, 它内部包含的信息有: uid(用户唯一的身份标识). time(当前时间的时间戳). sign(签名,token 的前几位以哈希算法压缩成的一定长度的十 ...
- 安卓10.0蓝牙HIDL的直通式初始化流程
本文仅介绍扼要的流程,没有系统化介绍. 首先从system\bt\hci\src\hci_layer_android.cc文件的函数void hci_initialize() 开始初始化: void ...
- 流量运营(pvuv跳出率漏斗abtest)
AARRR模型 1. 激活: 拉新,对用户来源渠道进行分析,哪些合作.投放渠道对我们产品更合适 2. 注册: 流量激活之后,如果用户只是点进来就走了,也没什么用,合适的产品功能切合用户需求,才会有转化 ...
- JAVA——》微信分账
做一个推荐分享的功能,场景:每推荐成功奖励推荐人一定的推荐金. 这里,我就用调用了微信支付分账接口.链接:https://pay.weixin.qq.com/wiki/doc/api/allocati ...
- Java Fastjson Unserialize WriteUp
Java Fastjson Unserialize 题目地址: https://ctf.bugku.com/challenges/detail/id/339.html 1. 查看网页源代码 <s ...
- LeetCode刷题感想之DFS
在剑指Offer里专门有一个部分(大概是连续十几题的样子)考察了 DFS ,也就是深度优先遍历,感觉DFS 也是一种套路,只要思路找对,套一下思路也可以了,在这里记录一下. 在很多Leetcode 的 ...
- if (()) [[]] [] 条件表达式比较示例
a.b的ASCII码是 097.098ASCII码 参考 http://www.51hei.com/mcu/4342.html 1. if (()) a=3; b=2 时,if (( a > b ...
- 项目:在wiki标记中添加无序列表(split、join巩固)
# coding: utf-8 import pyperclip text = pyperclip.paste() lines = text.split("\n") for i i ...
- JAVA 学习打卡 day1
2022-04-21 21:03:26 1.java程序的注释 (1)单行注释,就是在注释内容前面加双斜线(//) (2)多行注释,就是在注释内容前面以单斜线加一个星形标记(/*)开头,并在注释内容末 ...