"蔚来杯"2022牛客暑期多校训练营(加赛)
[题目链接]("蔚来杯"2022牛客暑期多校训练营(加赛)_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ (nowcoder.com))
M Maimai DX 2077
题目大意
某个音游有四种音符,每种音符有五个判定。不同音符的不同判定会获得不同的基础分数。绝赞的判定会单独计算分数。给定一次游玩中,每种音符每种判定的数量,问达成度。
题解
见代码。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
double a[10][10] = {{1, 1, 0.8, 0.5, 0}, {2, 2, 1.6, 1.0, 0}, {3, 3, 2.4, 1.5, 0}, {5, 5, 2.5, 2, 0}};
double b[10] = {1, 0.5, 0.4, 0.3, 0};
double num[10][10];
double A, B, A0, B0;
int main()
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 5; j++)
{
cin >> num[i][j];
A0 += num[i][j] * a[i][j];
A += num[i][j] * a[i][0];
}
}
for (int i = 0; i < 5; i++)
{
B0 += num[3][i] * b[i];
B += num[3][i] * b[0];
}
cout << fixed << setprecision(9) << A0 / A * 100 + B0 / B << endl;
return 0;
}
E Everyone is bot
题目大意
有 n 个人打算在群里复读。
一次复读的过程如下:每一轮,n 个人按照编号从小到大依次执行以下操作。
① 如果这个人在前几轮已经进行过复读,他不会再次复读。也就是说,每个人最多只会复读一次。
② 否则他可以选择是否进行复读。
如果某一轮没有人进行复读,那么复读的过程结束。
对于第 i 个人,如果他是所有人中第 j 个进行复读的,他会获得 a[i] [j] 瓶冰红茶。
但是如果他是所有进行了复读的人当中倒数第 p 个进行复读的人,那么他不会获得任何冰红茶,并且需要交出154 瓶冰红茶。
每个人都想最大化自己获得的冰红茶数量,求每个人会拿到多少冰红茶。
题解
思维题。复读人数是 n % p,且是前 n % p个人。
如果当前已经有 n − p 个人复读了,那么后面不会有任何人复读。因为一旦有人复读,剩下的人必然都会参与复读,那么这个人就会被禁言。所以谁都不会这么做。
同样,如果有 n − 2p 个人复读了,那么后面不会有任何人复读,因为一旦他复读了,接下来一定有 p − 1 个人加入复读。而这时候是 n − p 个人复读的状态,剩下 p 个人一定不会复读,那么他就被禁言了。
同样可以推出,如果当前复读人数是 n − kp 那么后面不会有人复读。
前 n mod p 个人必然一上来就复读。可以考虑如果有人不复读,后面本来没有机会的人必然会抓住机会,那么前面有人就会失去机会。
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e3 + 5;
int n, p;
int a[maxn][maxn];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> q;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
cin >> a[i][j];
for (int i = 1; i <= n % p; i++)
cout << a[i][i] << " ";
for (int i = n % p + 1; i <= n; i++)
cout << 0 << " ";
cout << endl;
return 0;
}
H Here is an Easy Problem of Zero-chan
题目大意
有一棵 n 个节点,且以 1 为根的有根树,第 i 个点的点权为 i。多次查询编号为 x 的点,∏ lca(i, x) (1<=i<=n)的末尾有多少个零。
题解
树形 dp 。
父节点u和子节点v,与1-n所有节点的lca中,只有包括子节点的子树这一部分不同,与父节点的lca为u,与子节点的lca为v。
转移式 dp[v] = dp[u] + size[v] * (cnt[v]2|5 − cnt[u]2|5),其中 size[v]代表 v 的子树大小,cnt[v]2|5 代表节点 v 能分解出多少个 2 或 5。
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
int n, q;
int siz[maxn], cnt2[maxn], cnt5[maxn], dp2[maxn], dp5[maxn];
vector<int> g[maxn];
int predfs(int u, int fa)
{
siz[u] = 1;
for (auto v : g[u])
{
if (v == fa)
continue;
siz[u] += predfs(v, u);
}
return siz[u];
}
void dfs(int u, int fa)
{
dp2[u] = dp2[fa] + siz[u] * (cnt2[u] - cnt2[fa]);
dp5[u] = dp5[fa] + siz[u] * (cnt5[u] - cnt5[fa]);
for (auto v : g[u])
{
if (v == fa)
continue;
dfs(v, u);
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
for (int i = 2; i < maxn; i++)
{
if (i % 2 == 0)
cnt2[i] = cnt2[i / 2] + 1;
if (i % 5 == 0)
cnt5[i] = cnt5[i / 5] + 1;
}
cin >> n >> q;
for (int i = 1; i < n; i++)
{
int u, v;
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
predfs(1, 0);
dfs(1, 0);
for (int i = 1; i <= q; i++)
{
int x;
cin >> x;
cout << min(dp2[x], dp5[x]) << endl;
}
return 0;
}
J Jellyfish and its dream
题目大意
给一个序列,值为 0 - 2。如果 (ai + 1) % 3 = a(i+1)%n,就可以将 ai 赋值为 a(i+1)%n。
问有限次操作后是否能使所有元素均相等。
题解
差分,后文中的变化全部指差分数组。
一次操作可以将相邻的 (2, 1) 变成 (0, 0),(1, 1) 变成 (2, 0),(0, 1) 变成 (1, 0)。不难发现 0 没有意义。可以通过 (0, 1) 变成 (1, 0)这个操作来移动 1的位置。
只要 1 的数量不少于 2 的数量即可。
说实话还不太懂。
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 5;
int t, n;
int a[maxn], cnt[5];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> t;
while (t--)
{
memset(cnt, 0, sizeof cnt);
cin >> n;
for (int i = 0; i < n; i++)
cin >> a[i];
for (int i = 0; i < n; i++)
{
cnt[(a[(i + 1) % n] - a[i] + 3) % 3]++;
}
if (cnt[1] >= cnt[2])
cout << "Yes" << endl;
else
cout << "No" << endl;
}
return 0;
}