"蔚来杯"2022牛客暑期多校训练营5
[题目链接]("蔚来杯"2022牛客暑期多校训练营5_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ (nowcoder.com))
K Headphones
题目大意
有N对耳机,Yasa拿出正好k对,NIO至少要取出多少只,能够比Yasa取出的多。耳机左右为一对,Yasa拿出的都是一对,NIO要取的是一只一只的。
题解
见代码。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 5;
int n, k;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
while (cin >> n >> k)
{
if ((n - k) * 2 <= n)
cout << -1 << endl;
else
cout << n + 1 << endl;
}
}
C Bit Transmission
题目大意
有个01组成的字符串,对某些位置询问是否是1,询问3n次,有至多一次询问返回的答案是错误的。问这些询问结果能否唯一确定字符串。
题解
见代码。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 5;
int n, x;
string s;
int yes[maxn], no[maxn];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n;
for (int i = 1; i <= 3 * n; i++)
{
cin >> x >> s;
if (s == "YES")
yes[x]++;
else
no[x]++;
}
s = "";
bool ok = 1;
for (int i = 0; i < n; i++)
{
if (no[i] && yes[i])
{
if (ok)
ok = 0;
else
{
cout << -1 << endl;
return 0;
}
if (yes[i] == 1 && no[i] == 1)
{
cout << -1 << endl;
return 0;
}
else if (no[i] == 1)
{
s += "1";
}
else if (yes[i] == 1)
{
s += "0";
}
else
{
cout << -1 << endl;
return 0;
}
}
else
{
if (no[i])
s += "0";
else
s += "1";
}
}
cout << s << endl;
return 0;
}
B Watches
题目大意
给定n件商品的价格,如果你选购k件商品,那么购买第i件物品的花费就是ai+k*i,问最多能买多少件(第i件是原序列中的第i个)。
题解
二分+贪心,判定是否能选择k件物品,总花费不超过M元。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 5;
int n, m;
int a[maxn], b[maxn];
bool checked(int k)
{
int ans = 0;
for (int i = 1; i <= n; i++)
b[i] = a[i] + k * i;
sort(b + 1, b + 1 + n);
for (int i = 1; i <= k; i++)
{
ans += b[i];
if (ans > m)
return false;
}
return true;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
while (cin >> n >> m)
{
for (int i = 1; i <= n; i++)
cin >> a[i];
int l = 0, r = n, mid, ans;
while (l <= r)
{
mid = (l + r) >> 1;
if (checked(mid))
{
ans = mid;
l = mid + 1;
}
else
{
r = mid - 1;
}
}
cout << ans << endl;
}
}
A Don’t Starve
题目大意
给定n个点有食物(每个点可以吃多次),每个点有一个坐标,对于行走的规则是每一步都必须严格短于上一步,问最优的方案下能够吃到多少次食物。
题解
首先枚举出所有的边,然后从大到小排序,然后每次枚举长度相同的边。
定义f[i]为目前状态下,到达点i获得的最大的食物。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e3 + 5;
const int Max = 0x3f3f3f3f;
int n;
int x[maxn], y[maxn];
struct Edge
{
int u, v, dis;
Edge(int u = 0, int v = 0, int dis = 0) : u(u), v(v), dis(dis) {}
bool operator<(const Edge &a) const
{
return dis > a.dis;
}
};
vector<Edge> e;
int f[maxn], g[maxn];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
memset(f, -Max, sizeof f);
cin >> n;
for (int i = 1; i <= n; i++)
cin >> x[i] >> y[i];
for (int i = 0; i <= n; i++)
{
for (int j = 1; j <= n; j++)
if (i != j)
e.push_back(Edge(i, j, pow(x[j] - x[i], 2) + pow(y[j] - y[i], 2)));
}
sort(e.begin(), e.end());
f[0] = 0;
for (int i = 0, j = 0; i < e.size(); i = j)
{
vector<Edge> v;
for (; j < e.size() && e[i].dis == e[j].dis; j++)
v.push_back(e[j]);
for (auto e : v)
g[e.v] = -Max;
for (auto e : v)
g[e.v] = max(g[e.v], f[e.u] + 1);
for (auto e : v)
f[e.v] = max(f[e.v], g[e.v]);
}
cout << *max_element(f, f + n + 1) << endl;
return 0;
}
H Cutting Papers
题目大意
给出一个不等式,问这个不等式构成的封闭区域和以这个封闭区域中心为圆心的圆形的面积并。
题解
根据不等式画出封闭区域,直接计算圆形和封闭区域的并集。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e3 + 5;
const int pi = acos(-1);
double n;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n;
cout << fixed << setprecision(10) << n * n * (4 - pi) / 8 << endl;
return 0;
}