A. Adjacent Digit Sums
题目大意
给你x和y作为数位之和,问是否存在n和n+1满足
解题思路
如果不进位显然xy只相差1,进位会让末尾的9都变成0,会不停的-9然后+1,所以只需要检查(x-y+1)/9是不是非负整数即可
代码实现
C++
#include <bits/stdc++.h>
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int tt;
std::cin >> tt;
while (tt--) {
int x, y;
std::cin >> x >> y;
if ((x - y + 1) % 9 == 0 && x - y + 1 >= 0) {
std::cout << "Yes\n";
} else {
std::cout << "No\n";
}
}
}
B. Two Large Bags
题目大意
给你两个数组ab,其中b为空,你可以选择a中元素放到b,如果选择的元素已经存在于b中,则可以把这个元素+1,问最后两个数组能不能相等
解题思路
有多个的时候,小的数字可以变成大的数字,所以只要让小的数字不断配对之后增大,看最后是否能全都匹配上就行
代码实现
C++
#include <bits/stdc++.h>
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int tt;
std::cin >> tt;
while (tt--) {
int n, f = 1;
std::cin >> n;
std::vector<int> a(n);
std::map<int, int> mp;
for (int i = 0; i < n; i++) {
std::cin >> a[i];
mp[a[i]]++;
}
for (auto it = mp.begin(); it != mp.end(); it++) {
if (it->second == 1) {
f = 0;
} else if (it->second) {
mp[it->first + 1] += it->second - 2;
}
}
if (f) {
std::cout << "Yes\n";
} else {
std::cout << "No\n";
}
}
}
C. Devyatkino
题目大意
给你一个正整数n,每次操作可以加上任意位数的9,问要操作多少次才会出现7
解题思路
显然答案至多是7,而加的数字都形如 1 0 x − 1 10^x - 1 10x−1,其实就是个位-1之后对指定的位置+1即可,所以每次只需要枚举相同值的数量即可
代码实现
C++
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int tt;
std::cin >> tt;
while (tt--) {
int n;
std::cin >> n;
std::string s = std::to_string(n);
if (s.find('7') != -1) {
std::cout << 0 << '\n';
continue;
}
std::vector<i64> nums = {9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999, 9999999999};
for (int i = 1, f = 1; i <= 7 && f; i++) {
for (int j = 0; j < 10 && f; j++) {
if (std::to_string(n + i * nums[j]).find('7') != -1) {
std::cout << i << "\n";
f = 0;
break;
}
}
}
}
}
D. Object Identification
题目大意
交互题,给你一个x数组,存在另外一个未知数组y,可以询问x中i位置和y中j位置,回答你的可能是有向图两点((对象A))间最短路,也可能是坐标上两点((对象B))的曼哈顿距离,请用两次询问确定对象
解题思路
简单观察可以发现如果出现了0则一定是图(没有路径),如果是坐标系则ij一定等于ji,显然我们每次的询问就是ij ji,同时要看回答是否有0。所以对于x不是排列的情况,很容易就能找到一条不存在的边来判断这是哪个对象;对于排列来说,如果是曼哈顿距离任何选择都没有区别,而图则不同,题目给了最短路,因此我们可以往最长的方向考虑,发现选择1和n时是图的话路径最长就是n-1,并且如果存在这样的路径,那么反过来的路径就不存在了,而曼哈顿距离一定会大于等于n-1,因此只用询问1和n的位置即可
代码实现
C++
#include <bits/stdc++.h>
using i64 = long long;
int main() {
int tt;
std::cin >> tt;
while (tt--) {
int n;
std::cin >> n;
std::vector<int> x(n + 1), f(n + 1);
for (int i = 1; i <= n; i++) {
std::cin >> x[i];
f[x[i]] = 1;
}
int aski = -1, askj = -1, dist1, dist2;
for (int i = 1; i <= n; i++) {
if (!f[i]) {
aski = i;
break;
}
}
if (aski == -1) {
for (int i = 1; i <= n; i++) {
if (x[i] == 1) {
aski = i;
}
if (x[i] == n) {
askj = i;
}
}
std::cout << "? " << aski << " " << askj << std::endl;
std::cin >> dist1;
std::cout << "? " << askj << " " << aski << std::endl;
std::cin >> dist2;
if (dist1 == dist2 && dist1 >= n - 1) {
std::cout << "! B" << std::endl;
} else {
std::cout << "! A" << std::endl;
}
} else {
askj = aski + 1;
if (aski == n) {
askj = n - 1;
}
std::cout << "? " << aski << " " << askj << std::endl;
std::cin >> dist1;
std::cout << "? " << askj << " " << aski << std::endl;
std::cin >> dist2;
if (dist1 == dist2 && dist1 * dist2) {
std::cout << "! B" << std::endl;
} else {
std::cout << "! A" << std::endl;
}
}
}
}
E. White Magic
题目大意
定义神奇序列为从任意位置将序列一分为二,左侧的min都不小于右侧的mex,给你一个数组,求数组最长神奇子序列
解题思路
如果序列没有0显然满足条件,显然序列也不会有两个0,所以只需要考虑在什么时候加入0。简单贪心可以发现最左的0是最优的,因此只需要看保留最左侧的0是否能满足条件即可。
代码实现
C++
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int tt;
std::cin >> tt;
while (tt--) {
int n, ans = 0, f = 0;
std::cin >> n;
std::vector<int> a;
for (int i = 0; i < n; i++) {
int x;
std::cin >> x;
if (x != 0) {
ans++;
a.push_back(x);
} else if (!f) {
ans++;
a.push_back(x);
f = 1;
}
}
int m = a.size(), mex = 0;
std::vector<int> pre = a, cnt(m);
for (int i = 1; i < m; i++) {
pre[i] = std::min(pre[i], pre[i - 1]);
}
for (int i = m - 1; i >= 1; i--) {
if (a[i] < m) {
cnt[a[i]] = 1;
}
while (mex < m && cnt[mex]) {
mex++;
}
if (mex > pre[i - 1]) {
ans--;
break;
}
}
std::cout << ans << "\n";
}
}