SMU Autumn 2023 Round 4(Div.1+2)
SMU Autumn 2023 Round 4(Div.1+2)
A. Access Denied
通过分析样例可以得知如果所猜字符串与答案字符串长度不同,则只要\(5ms\),且答案最多\(20\)个字符,因此我们可以先猜20次去核对总字符串长度,如果核对过程中直接猜中了,那就不用继续猜了,又继续分析样例可以得知每遍历一个字符需要消耗\(9ms\),那我们可以对每一位答案的字母一位位地去猜,最多猜\(62\)次,然后最终确定答案字符串,我们在构造初始字符串的时候必须是\(62\)个字符以内的,且又因为构造的是\(62\)位字母内的,所以不排除答案的某些位和我们构造的初始字符串是一样的,导致我们去一位位猜测的时候会刚好有初始的某些位和答案的一样,所以程序就会继续跑,最后返回的结果不是比上一次猜测刚好多\(9ms\),而是更多
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
typedef pair<i64, i64> PII;
char ans[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4',
'5', '6', '7', '8', '9'};
int main() {
int t = 0;
string s, now;
for (int i = 1; i <= 20; i ++) {
t = 0;
s = string(i, '0');
cout << s << endl;
getline(cin, now);
if (now == "ACCESS GRANTED") exit(0);
for (auto j : now)
if (isdigit(j)) t = t * 10 + (j - '0');
if (t != 5) {
t = i;
break;
}
}
string res = string(t, '0');
int T;
for (int i = 0; i < t; i ++) {
for (int j = 0; j < 62; j ++) {
T = 0;
res[i] = ans[j];
cout << res << endl;
getline(cin, now);
if (now == "ACCESS GRANTED") exit(0);
for (auto k : now)
if (isdigit(k)) T = T * 10 + (k - '0');
if (T >= 5 + (i + 2) * 9)
break;
}
}
return 0;
}
J. Jet Set
由题目可知,极点经过了所有经线,且经过所有经线就认为是环游了世界,所以对于两个地点,如果它们的经度刚好相差180,那么这两点走经过经线的那段圆弧即是最短的,也就一定环游了世界,对于其余的点,我们只要看它们两者经度差与180比较,大于180的,说明走反着走更短,否则就正着走更短,且数据较小,我们可以直接循环去标记他经过哪些经线即可
#include <bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';
using namespace std;
using i64 = long long;
typedef pair<i64, i64> PII;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<int> Wei(n + 1);
for(int i = 0;i < n;i ++){
int x;
cin >> x >> Wei[i];
Wei[i] += 180;
}
Wei[n] = Wei[0];
vector<bool> vis(996,false);
for(int i = 1;i <= n;i ++){
if(abs(Wei[i] - Wei[i - 1]) == 180){
cout << "yes\n";
return 0;
}else if(abs(Wei[i] - Wei[i - 1]) > 180){
for(int j = 0;j <= min(Wei[i],Wei[i - 1]) * 2;j ++){
vis[j] = true;
}
for(int j = max(Wei[i], Wei[i - 1]) * 2;j <= 720;j ++){
vis[j] = true;
}
}else{
for(int j = min(Wei[i], Wei[i - 1]) * 2;j <= max(Wei[i], Wei[i - 1]) * 2;j ++)
vis[j] = true;
}
}
for(int i = 0;i <= 720;i ++){
if(!vis[i]){
printf("no %.1lf\n", (double)i / 2 - 180);
return 0;
}
}
cout << "yes\n";
return 0;
}
K. Knitpicking
题意就是给你一堆混合在一起的袜子,问你最少拿多少只袜子能够配队,\(left\)和\(right\)是分开配对,\(any\)则左右皆可,对于同一类型的袜子,最坏情况下肯定是拿到左右袜子中数量最多的那一堆,对于某类只有\(any\)类型的,我们只需拿\(1\)只即可,把这些加起来,最后随便再拿一只都能完成配对
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
typedef pair<i64, i64> PII;
map<string,array<int,3>> cs;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
bool match = false;
for(int i = 0;i < n;i ++){
string s1,s2;
int k;
cin >> s1 >> s2 >> k;
if(s2 == "left") cs[s1][0] = k;
else if(s2 == "right") cs[s1][1] = k;
else cs[s1][2] = k;
if(s2 == "any" && k > 1) match = true;
else if(s2 == "left" && cs[s1][1]) match = true;
else if(s2 == "right" && cs[s1][0]) match = true;
}
if(!match){
cout << "impossible\n";
}else{
int ans = 0;
for(auto [x,y] : cs){
if(!y[0] && !y[1]) ans ++;
else ans += max(y[0], y[1]);
}
cout << ans + 1 << '\n';
}
return 0;
}