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;
}
posted @ 2023-09-18 01:47  Ke_scholar  阅读(24)  评论(0编辑  收藏  举报