Educational Codeforces Round 139 (Rated for Div. 2)(A~E)

Source

A. Extremely Round

定义一个数中仅存在一位非0,它是extremely round,计算1~n中有几个满足条件的数。

思路:直接计算即可。

AC Code:

#include <bits/stdc++.h>

typedef long long ll;
const int N = 1e5 + 5;
int t, n;

int count(int x) {
	int ans = 0;
	while(x) {
		if(x >= 10) ans += 9;
		else ans += x;
		x /= 10;
	}
	return ans;
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);
	std::cin >> t;
	while(t --) {
		std::cin >> n;
		std::cout << count(n) << '\n';
	}
	return 0;
}

 B. Notepad#

每次操作可以在字符串末尾加上任意一个字母,或者选择已经存在的一段子串加到后面,给出字符串长度n,判断是否能在最多n-1次操作后组成字符串。

思路:很显然,只要存在相邻两位在字符串中出现过两次,即可满足条件,用map可以过。

AC Code:

#include <bits/stdc++.h>

typedef long long ll;
typedef std::pair<char, char> PII;
const int N = 1e5 + 5;
int t, n;
std::string s;

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);
	std::cin >> t;
	std::map<PII, int> mp;
	while(t --) {
		std::cin >> n >> s;
		mp.clear();
		bool flag = false;
		for(int i = 1; i < n; i ++) {
			if(!mp[{s[i - 1], s[i]}])
				mp[{s[i - 1], s[i]}] = i;
			else if(i - mp[{s[i - 1], s[i]}] > 1){
				flag = true;
				break;
			}
		}
		std::cout << (flag ? "YES" : "NO") << '\n';
	}
	return 0;
}

C. Hamiltonian Wall

 给出两行字符串,每一列至少有一个B,是否存在一条路径能够一笔画走完所有的B且没有重复。

思路:数据范围很小,直接搜索即可,注意行列的优先级,能先走列必然先走列。

AC Code:

#include <bits/stdc++.h>

typedef long long ll;
const int N = 2e5 + 5;
int t, n, cnt, ans;
std::string s[4];
bool vis[2][N];

void DFS(int x, int y, int c) {
	ans = std::max(ans, c);
	vis[x][y] = 1;
	if(x == 0) {
		if(s[x + 1][y] == 'B' && !vis[x + 1][y])
			DFS(x + 1, y, c + 1);
		else if(s[x][y + 1] == 'B' && !vis[x][y + 1])
			DFS(x, y + 1, c + 1);
		else return;
	}
	else if(x == 1) {
		if(s[x - 1][y] == 'B' && !vis[x - 1][y])
			DFS(x - 1, y, c + 1);
		else if(s[x][y + 1] == 'B' && !vis[x][y + 1])
			DFS(x, y + 1, c + 1);
		else return;
	}
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);
	std::cin >> t;
	while(t --) {
		std::cin >> n;
		memset(vis, 0, sizeof(vis));
		for(int i = 0; i < 2; i ++)
			std::cin >> s[i];
		cnt = 0, ans = 0;
		for(int i = 0; i < 2; i ++) {
			for(int j = 0; j < n; j ++) {
				if(s[i][j] == 'B')
					cnt ++;
			}
		}
		s[0] = s[0] + '*', s[1] = s[1] + '*';
		if(s[0][0] == 'B')
			DFS(0, 0, 1);
		memset(vis, 0, sizeof(vis));
		if(s[1][0] == 'B')
			DFS(1, 0, 1);
		std::cout << (ans == cnt ? "YES" : "NO") << '\n';
	}
	return 0;
}

os:赛后看到佬们写的题解都是用的DP,我不会DP,就搜索咯

D. Lucky Chains

给出二元组x,y,每次给两个数+1,问最多几次操作后两数的gcd>1。

思路:根据辗转相除,gcd(a + x, b + x) = gcd(a + x, b - a),b-a为定值,所以思路就很容易了,分解b-a的所有质因子,判断x能达到的最小值,设p为b-a的质因子,即求p - (b - a) % p的最小值,注意时间,这个题时限卡的挺紧的,注意细节的优化。

AC Code:

#include <bits/stdc++.h>

typedef long long ll;
#define INF 0x3f3f3f3f
const int N = 1e7 + 5;
int t, x, y;
int prime[N], tot;
bool mark[N];

void oula() {
    for(int i = 2; i <= N; i ++) {
        if(!mark[i])
            prime[++ tot] = i;
        for(int j = 1; j <= tot; j ++) {
            if(i * prime[j] > N) break;
            mark[i * prime[j]] = 1;
            if(i % prime[j] == 0) break;
        }
    }
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);
	std::cin >> t;
	oula();
	while(t --) {
		std::cin >> x >> y;
		if(std::__gcd(x, y) > 1) {
			std::cout << 0 << '\n';
			continue;
		}
		int res = y - x, pos = 1, ans = INF;
		while(prime[pos] <= sqrt(res)) {
			if(res % prime[pos]) {
				pos ++;
				continue;
			}
			while(res % prime[pos] == 0) res /= prime[pos];
			ans = std::min(ans, prime[pos] - x % prime[pos]);
			pos ++;
		}
		if(res > 1) ans = std::min(ans, res - x % res);
		std::cout << (ans == INF ? -1 : ans) << '\n';
	}
	return 0;
}

有个逆天师弟把E都搞出来了,一整个被薄纱了