H:
H-Genshin Impact's Fault_2024牛客暑期多校训练营6 (nowcoder.com)
题意:
在《原神》游戏中,许愿是一种尝试获得特定角色的行为。
在这个问题中,许愿有四种可能的结果:
- 3星武器,
- 4星武器/角色,
- 5星非促销武器/角色,
- 5星促销武器/角色。这里,我们不区分武器和角色,并分别用3、4、5和U来表示每个结果。
制订许愿的一些规则:
- 每连续10个许愿中不会只包含3星武器。
- 每连续90个许愿中必须至少包含一个5星武器/角色,不论是否是促销的。
- 每两个相邻的5星武器/角色之间必须至少有一个是促销的。这里,如果两个5星武器/角色之间所有的许愿都不是5星武器/角色,则称这两个5星为相邻。
现在给你一个许愿列表。判断它是否符合上述规则。
输入描述: 第一行包含一个整数T(1≤T≤10^5),代表测试用例的数量。
对于每个测试用例,单独一行包含一个字符串S(1≤|S|≤10^6),字符串仅包含3、4、5和U。
保证∑|S|≤10^6。
输出描述: 对于每个测试用例,如果符合上述规则,输出"valid",否则输出"invalid"。
解析:
这道题目的注意点就是对于规则二来说,90个许愿可以是从0~89,也可以是1~90,2~91。因此我们可以用滑动窗口来解决。规则三的巧妙的地方就是在原本字符串中提取5和U,构造成一个新的字符串,查找是否存在55即可。
#include<bits/stdc++.h>
using namespace std;
void solve(string s) {
bool invalid = false;
// 检查连续的10个3星
int p = s.find("3333333333");
if (p != -1) invalid = true;
// 每90个许愿至少有一个5星或促销U
int count5U = 0, start = 0;
for (int i = 0; i < s.size(); i++) {
if (s[i] == 'U' || s[i] == '5') {
count5U++;
}
// 完成90个字符的检查
if (i - start + 1 == 90) {
if (count5U == 0) {
invalid = true;
break;
}
// 移动窗口
if (s[start] == 'U' || s[start] == '5') {
count5U--;
}
start++;
}
}
// 检查连续两个5星之间必须有促销U
string ss;
for (char ch : s) {
if (ch == 'U' || ch == '5') ss += ch;
}
if (ss.find("55") != -1) invalid = true;
if (invalid) cout << "invalid" << '\n';
else cout << "valid" << '\n';
}
int main() {
int t; cin >> t;
while (t--) {
string s; cin >> s;
solve(s);
}
return 0;
}
B:
B-Cake 2_2024牛客暑期多校训练营6 (nowcoder.com)
题目大意:
对于一个给定边数为 n 的规则多边形,通过连接顶点 i 和 (i+k)mod n 的线段来切割蛋糕,我们需要确定切割后的区域数。
解析:
画几个图即可
例1:n = 8, k = 4,共有8个区域
例2: n = 8, k = 5 ,共有25个区域
例3:n = 7, k = 3,共有22个区域。
从例1我们可以知道,当n = 2 * k,区域个数就为n
从例3 我们可以知道,当n != 2 * k,区域个数可能为n * k + 1
从例2我们可知,n * k + 1不满足区域个数,区域个数为n * (n - k) + 1,此时 n - k < k;
综上所述,当n = 2 * k,区域个数就为n。否则就为 n * min (n - k, k) + 1
本题需要开long long。
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
int main() {
ll n, k;
cin >> n >> k;
ll result = 0;
if(2*k == n) result = n;
else result = n * min(k,n-k) + 1;
cout << result << endl;
return 0;
}