2021牛客暑期多校训练营1 个人补题记录
比赛链接:Here
A - Alice and Bob (Game,打表)
emmm,博弈签到题
题意:
Alice(先手) 和 Bob 面前有两堆石头,石头数量为
每次操作可从一堆石头中取出
哪一方无法执行操作则判负
我们知道当面临两堆石头数量为(0,0)时为失败,那么如果能一次操作能取光石头此时为必胜态
我们用一个二维数组
证明如下:
若存在
这样我们的时间复杂度大约在 cin
等操作,数组也需要开成 bool
的来节省运算时间。
【AC Code】
#include<iostream>
#include<stdio.h>
using namespace std;
bool f[5010][5010] = {false};
int main() {
// cin.tie(nullptr)->sync_with_stdio(false);
//自小到大枚举i,j
for (int i = 0; i <= 5000; i++)
for (int j = 0; j <= 5000; j++) {
if (f[i][j] == 0) { //对于每种必败态进行拓展
//f[i][j]与f[j][i]是等价的
for (int k = 1; k + i <= 5000; k++)for (int s = 0; s * k + j <= 5000; s++)f[i + k][j + s * k] = 1;
for (int k = 1; k + j <= 5000; k++)for (int s = 0; s * k + i <= 5000; s++)f[i + s * k][j + k] = 1;
}
}
int n, m, t;
scanf("%d", &t);
while (t--) {
scanf("%d%d", &n, &m);
if (!f[n][m])puts("Bob");
else puts("Alice");
}
}
看了下其他人的代码,个个打表也是神了
B - Ball Dropping (Math)
给一个中间空的等腰梯形。
然后有一个圆,问是否能从中间穿过梯形。
借用 纯神 的说法:
这道题是一个数学题,简单画个图即可
看到梯形我们考虑用相似三角。
首先两个相似求出
然后由于它是等腰,我们可以继续求。
(注意这个球掉到上面的地方与墙面碰到的两个点组成的直线不是直径)
(我当时就搞错了,搞了半天才发现,两个墙壁是它的切线)
用勾股可以得到
然后根据相似,可以得到
【AC Code】
using ld = long double;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
ld r, a, b, h;
scanf("%Lf %Lf %Lf %Lf", &r, &a, &b, &h);
if (a < b) swap(a, b);
if ((r * 2.0) <= b) printf("Drop");
else {
printf("Stuck\n");
ld beta = b * h / (a - b);
ld side = sqrt((a / 2) * (a / 2) + (beta + h) * (beta + h));
printf("%Lf", side * r / (a / 2) - beta);
}
}
C - Cut the Tree
待补
D - Determine the Photo Position (签到)
题意:
给出一个矩阵,问有多少个地方有连续的
暴力模拟枚举,
记录一个
然后每次搞完看一下,如果
【AC Code】
int main() {
// cin.tie(nullptr)->sync_with_stdio(false);
int n, m;
cin >> n >> m;
int a[n + 1][n + 1], ans = 0;
for (int i = 1; i <= n; ++i) {
int num = 0;
for (int j = 1; j <= n; ++j) {
scanf("%1d", &a[i][j]);
if (a[i][j] == 0)num++;
else num = 0;
if (num >= m)ans++;
}
}
cout << ans << "\n";
}
E - Escape along Water Pipe
待补
F - Find 3-friendly Integers (签到)
题意:
3-friendly定义:一个正整数的各个位数能整除 3 则称这个数为 3-friendly.
比如,104中 0 可整除 3,124中 12 可整除 3
问在区间
这个很容易知道三位数以上的值随便组合都能整除 3
所以我们可以先序找出 1 ~ 100 中所有非 3-friendly 的数,然后在区间计数时删去即可
【AC Code】记得使用 long long
using ll = long long;
int vis[] = {1, 2, 4, 5, 7, 8, 11, 14, 17, 22, 25, 28, 41, 44, 47, 52, 55, 58, 71, 74, 77, 82, 85, 88};
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int _; for (cin >> _; _--;) {
ll l, r, k = 0;
cin >> l >> r;
for (int i = 0; i < 24; ++i) {
if (vis[i] >= l and vis[i] <= r)k++;
}
cout << r - l + 1 - k << "\n";
}
}
G - Game of Swapping Numbers
题意:
给两个数组a,b,现在可以交换a中的数k次,求
首先我们思考一下什么样的两个数交换后的结果会大:
假如有两对数:
原结果为
- 如果
&& && :
那么原结果为
交换后结果为:
结果之差为 - 如果
&& && :
那么原结果为
交换后结果为:
结果之差为
如此分析下去:
我们发现可以使结果增长的情况为一对的最小值大于另一对的最大值时.
然后当
【AC Code】
const int N = 5e5 + 7;
ll a[N], b[N], Ma[N], Mi[N];
bool cmp(ll a, ll b) { return a > b;}
int main() {
int n, k;
cin >> n >> k;
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= n; i++) cin >> b[i];
ll ans = 0;
if (n == 2) {
if (k % 2) swap(a[1], a[2]);
ans = ans + abs(a[1] - b[1]) + abs(a[2] - b[2]);
} else {
for (int i = 1; i <= n; i++) {
ans = ans + abs(a[i] - b[i]);
Ma[i] = max(a[i], b[i]);
Mi[i] = min(a[i], b[i]);
}
sort(Mi + 1, Mi + n + 1, cmp);
sort(Ma + 1, Ma + n + 1);
for (int i = 1; i <= k && i <= n; i++) {
if (Mi[i] > Ma[i]) ans = ans + 2 * (Mi[i] - Ma[i]);
else break;
}
}
cout << ans << endl;
return 0;
}
H - Hash Function
待补
I - Increasing Subsequence (DP)
题意:
给定一个长度为
思路:
期望
【AC Code】
const int mod = 998244353, N = 5e3 + 10;
int p[N], c[N], sum[N], pos[N], inv[N];
int dp[N][N];
int qpow(int a, int b) {
int ans = 1;
for (; b; b >>= 1, a = 1ll * a * a % mod)
if (b & 1)ans = 1ll * ans * a % mod;
return ans;
}
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int n;
cin >> n;
for (int i = 1; i <= n; i += 1) {
cin >> p[i];
pos[p[i]] = i;
inv[i] = qpow(i, mod - 2);
}
for (int j = n; j > 0; j -= 1) {
for (int i = 0; i <= n; i += 1) c[i] = sum[i] = 0;
for (int t = j + 1; t <= n; t += 1) {
c[pos[t]] = 1;
sum[pos[t]] = dp[j][t];
}
for (int i = n - 1; i >= 0; i -= 1) {
c[i] += c[i + 1];
sum[i] = (sum[i] + sum[i + 1]) % mod;
}
for (int i = j - 1; i >= 0; i -= 1) {
int tot = c[pos[i]];
int sm = sum[pos[i]];
if (tot) dp[i][j] = (1ll * inv[tot] * sm + 1) % mod;
}
}
ll ans = 0;
for (int i = 1; i <= n; i += 1)ans = (ans + dp[0][i]) % mod;
cout << (1ll * ans * inv[n] % mod + 1) % mod;
}
J - Journey among Railway Stations
待补
K - Knowledge Test about Match
待补
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· 分享4款.NET开源、免费、实用的商城系统
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 全程不用写代码,我用AI程序员写了一个飞机大战
2020-07-20 signed main 和 int main 的区别
2020-07-20 Codeforces Round #656 (Div. 3)部分题解