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都搞出来了,一整个被薄纱了