B3711 [语言月赛202302] 惊蛰
文章目录
题目描述
给定一个正整数,规定一次操作为选定 l , r l,r l,r,删去所有从后往前数第 l ∼ r l\sim r l∼r 位的数字,并且将剩下的数字组成一个新的正整数。如 123456 123456 123456 删去从后往前数的第 2 ∼ 3 2\sim 3 2∼3 位就会变成 1236 1236 1236。
现在有 T T T 组询问,每次询问给定一个正整数 n n n,你需要回答:对于这个正整数,能否通过最多一次操作(不操作也算)将其变为 4 4 4 的倍数。
但是请注意,不能把所有的数位全都删完。
输入格式
输入共 T + 1 T+1 T+1 行。
输入的第一行,一个正整数 T T T。
接下来 T T T 行,每行一个正整数 n n n。保证 n n n 不包含前导零。
输出格式
输出共 T T T 行。
对于
T
T
T 组数据,每组数据需要输出
1
1
1 行,表示问题的答案。若可以,输出 Yes
,不可以,输出 No
。
样例 #1
样例输入 #1
3
234
1
286
样例输出 #1
Yes
No
Yes
样例 #2
样例输入 #2
1
2386
样例输出 #2
Yes
提示
样例 1 解释
对第一组数据:删去从后往前数第 2 ∼ 3 2\sim 3 2∼3 位,剩下的数是 4 4 4,是 4 4 4 的倍数。
对第二组数据:可以证明没有任何一种方案能够达成目标。
对第三组数据:删去从后往前数第 1 1 1 位,剩下的数是 28 28 28,是 4 4 4 的倍数。
数据范围
对于前
10
%
10\%
10% 的数据,保证
1
≤
n
≤
9
1\le n\le 9
1≤n≤9。
对于前
30
%
30\%
30% 的数据,保证
1
≤
T
≤
10
,
1
≤
n
≤
100
1\le T\le 10,1\le n\le 100
1≤T≤10,1≤n≤100。
对于另外
10
%
10\%
10% 的数据,保证
T
=
1
T=1
T=1。
对于前
60
%
60\%
60% 的数据,保证
1
≤
T
≤
10
,
1
≤
n
≤
1
0
9
1\le T\le 10,1\le n\le 10^9
1≤T≤10,1≤n≤109。
对于
100
%
100\%
100% 的数据,
1
≤
T
≤
1
0
2
,
1
≤
n
≤
1
0
18
1\le T\le 10^2,1\le n\le 10^{18}
1≤T≤102,1≤n≤1018。
以上题面来自 https://www.luogu.com.cn/problem/B3711。
PART1. 思路描述
题意可以简化成给你一个数,你可以删除 [ l , r ] [l,r] [l,r] 段,求是否可以只删除一次就让这个数能被 4 4 4 整除。
直接采用取模运算去取数未免有些太过麻烦,我们看到数据范围的 n n n 最多只有 18 18 18 位,可以考虑用字符串模拟,去枚举 l l l 和 r r r 求解即可。
string
类中 erase
函数的用法:
void erase(size_t pos, size_t len = 0);
表示从
p
o
s
pos
pos 位置开始删除
l
e
n
len
len 个字符,要删除
[
i
,
j
]
[i,j]
[i,j] 的字符可以写成 erase(i , j-i+1);
。
PART2. AC 代码
#include <algorithm>
#include <iostream>
using namespace std;
string num;
signed main()
{
int T;
for(cin >> T; T --; ){
cin >> num;
bool flag = false;
if(stoll(num) % 4 == 0){
flag = true;
}
for(int i = 0; i < num.size() && !flag; i ++){
for(int j = i; j < num.size(); j ++){
string temp = num;
if(i == 0 && j == num.size() - 1){ //题目中说了不可以全部删除
break;
}
temp.erase(i , j - i + 1); //从i到j共有j-i+1个字符
if(stoll(temp) % 4 == 0){
flag = true;
break;
}
}
}
if(flag == true){
cout << "Yes" << endl;
}else{
cout << "No" << endl;
}
}
return 0;
}
End
这里是 YLCHUP,谢谢大家!