【牛客小白月赛69】题解与分析A-F【蛋挞】【玩具】【开题顺序】【旅游】【等腰三角形(easy)】【等腰三角形(hard)】

🎈 作者：Eriktse
🎈 简介：19岁，211计算机在读，现役ACM银牌选手🏆力争以通俗易懂的方式讲解算法！❤️欢迎关注我，一起交流C++/Python算法。（优质好文持续更新中……）🚀
🎈 个人博客：www.eriktse.com

A-蛋挞

#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-玩具

#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。

#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-旅游

#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)

$$tan60\degree = tan(x+y)= \frac{tanx + tany}{1-tanx \times tany}$$

#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原创，创作不易，如果对您有帮助，欢迎小伙伴们点赞👍、收藏⭐、留言💬

Eriktse
4 声望0 粉丝

19岁，性别未知，ACM-ICPC现役选手，ICPC亚洲区域赛银牌摆烂人，CCPC某省赛铜牌蒟蒻，武汉某院校计算机科学与技术专业本科在读。

0 条评论