这次我第五十分钟的时候才想起来得做题,一共就九十分钟,服了。
A:a+b(easy)
题目描述
给定一个形式为a+b的表达式,其中a和b是0到9的一个整数,您需要对其进行求值并打印结果。
输入格式
第一行包含一个整数T(1≤T≤1000),表示测试样例组数。
接下来T行每行一个表达式。
输出格式
为每个表达式求值并打印结果。
输入样例
4
4+2
0+0
3+7
8+9
输出样例
6
0
10
17
解题思路:
直接写。
#include <iostream>
#include <string>
using namespace std;
int main() {
int T;
cin >> T;
while (T--) {
string expression;
cin >> expression;
int a = expression[0] - '0';
int b = expression[2] - '0';
int result = a + b;
cout << result << endl;
}
return 0;
}
B:a+b(hard)
题目描述
本题为A的hard版本,与easy版本的唯一区别在于a和b的范围不同。
给定一个形式为a+b(0≤a,b≤1014)的表达式,您需要对其进行求值并打印结果。
输入格式
第一行包含一个整数T(1≤T≤1000),表示测试样例组数。
接下来T行每行一个表达式。
输出格式
为每个表达式求值并打印结果。
输入样例
4
4+2
0+0
3+7
8+9
输出样例
6
0
10
17
解题思路:
因为这个是ACM赛制,所以说,要考虑时间复杂度,但是就是long long类型来定义也是远远不够的,事实上,遇到这种显然无法直接表示的运算时,通常就是采用字符串的方法来解决,核心就是字符与数字的转换。
#include <iostream>
#include <string>
using namespace std;
string addLargeNumbers(string num1, string num2) {
if (num1.length() < num2.length()) {
swap(num1, num2);
}
int carry = 0;
int n1 = num1.length(), n2 = num2.length();
string result = "";
for (int i = 0; i < n1; ++i) {
int sum = (num1[n1 - 1 - i] - '0') + (i < n2 ? num2[n2 - 1 - i] - '0' : 0) + carry;
carry = sum / 10;
result = to_string(sum % 10) + result;
}
if (carry) {
result = to_string(carry) + result;
}
return result;
}
int main() {
int T;
cin >> T;
while (T--) {
string expression;
cin >> expression;
size_t pos = expression.find('+');
string num1 = expression.substr(0, pos);
string num2 = expression.substr(pos + 1);
string result = addLargeNumbers(num1, num2);
cout << result << endl;
}
return 0;
}
C:最近不存在数字
题目描述
给定长度为n的数组a和一个整数b。
要求找出一个整数x满足:
- x∈/a,即x不存在于数组a中。
- ∣b−x∣最小。
若有多个x满足条件,取较小的x作为答案。
输入格式
注意:本题有多组测试样例!
第一行一个整数T表示测试用例个数。(1≤T≤10)
对于每组测试用例:
一行两个整数n,b(1≤n≤105,1≤b≤109)。
第二行n个整数表示ai(1≤ai≤109)。
数据保证:∑n≤2×105
输出格式
对于每组测试用例,输出一个整数表示答案。
输入样例
2
3 5
2 3 4
4 7
7 10 6 8
输出样例
5
5
解题思路:
这个题翻译一下,如果b不在数组a中,那么直接输出b,如果b这个数字位于a中,那就在数组中寻找一个与b差值最小的数字,并且取最小的那个,初始化 ans 为 b,表示最初的答案设定为 b。
初始化 minDiff 为一个较大的值 INT_MAX,用来存储当前最小的差距。遍历 -1、0、1 这三个相对于 b 的偏移量,对应着 b-1、b、b+1 这三个候选数。对于每个候选数,如果它在数组 a 中存在,则向下一个数移动,直到找到数组 a 中不存在的数。计算当前候选数与 b 的差距,并更新 minDiff 和 ans,以确保找到最接近 b 的且不在数组 a 中的数。核心思想是通过迭代 b-1、b、b+1 这三个数,找到在数组 a 中不存在的最接近 b 的数,并且保证在距离相等时选择较小的数。
#include <iostream>
#include <vector>
#include <set>
#include <cmath>
#include<climits>
using namespace std;
int main() {
int T;
cin >> T;
while (T--) {
int n, b;
cin >> n >> b;
set<int> a;
for (int i = 0; i < n; ++i) {
int num;
cin >> num;
a.insert(num);
}
int ans = b;
int minDiff = INT_MAX;
for (int i = -1; i <= 1; ++i) {
int candidate = b + i;
while (a.find(candidate) != a.end()) {
candidate += (i >= 0) ? 1 : -1;
}
int currentDiff = abs(b - candidate);
if (currentDiff < minDiff || (currentDiff == minDiff && candidate < ans)) {
minDiff = currentDiff;
ans = candidate;
}
}
cout << ans << endl;
}
return 0;
}
D:数字根
题目描述
非负整数的数字根是通过不断迭代对数字的每一位求和,直到得出一个一位数为止,这个一位数就是它的数字根。例如5的数字根是5,而38的数字根是2,求解过程如下:38→3+8=11→1+1=2。
现在阿慧得到了一个作业,要求找出第k个数字根为x的数字,但是她不会,所以请教了你来帮她解决这个麻烦。
输入描述
第一行一个整数T(1≤T≤1000),表示测试样例组数。
接下来T行,每行两个整数k,x(1≤k≤1012,1≤x≤9)。
输出描述
为每个测试样例打印一个整数,表示第𝑘k个数字根为x的整数。
输入样例
3
1 5
5 2
3 1
输出样例
5
38
19
解题思路:
我们将1~36写出来,
我们发现同一列中的数字元素数字根都相同,所以我们推测数字根出现的规律大致是以9为一个周期递推,而事实也正是如此。所以我们要找第𝑘k个数字根为𝑥x的数字,也就是在上述矩阵中第𝑘k行,第𝑥x列的元素,所以答案为(k−1)×9+x。
#include <iostream>
using namespace std;
void solve()
{
int k,x;
cin >> k >> x;
cout << (k - 1) * 9 + x << '\n';
}
int main()
{
int t;
cin >> t;
while(t--)
solve();
return 0;
}
E:再短一点
题目描述
当一个长度为m的二进制字符串T是幸运的,我们可以通过任意顺序执行以下两种操作m−1来获得长度为1的字符串:
-
选择T中任意等于01的子字符串,将其替换为1。
-
选择T中任何等于10的子字符串,然后将其替换为0。
例如,如果T=001,我们可以选择子字符串[T2T3]并执行第一个操作。得到T=01。
您将得到一个长度为n的二进制字符串S,索引从1到n。找出(l,r)(1≤l≤r≤n)使得S[l…r](S从l到r的子字符串)是一个幸运的字符串的整数对的个数。
输入描述
第一行包含一个整数t(1≤t≤1000)—测试用例的数量。下面是测试用例的描述。
每个测试用例的第一行包含一个整数n(1≤n≤2⋅105)——大小为S。
每个测试用例的第二行包含一个由n字符S1S2…Sn组成的二进制字符串S。(每个1≤i≤n对应Si= 0或Si= 1)
保证所有测试用例的n之和不超过2⋅105。
输出描述
对于每个测试用例,输出使S[l…r](S从l到r的子字符串)为偏执字符串的整数对(l,r)1≤l≤r≤n的个数。
输入样例1
5
1
1
2
01
3
100
4
1001
5
11111
输出样例1
1
3
4
8
5
样例解释
在第一个示例中,S已经具有长度1,不需要任何操作。
在第二个示例中,S的所有子字符串都是幸运的。对于整个字符串,执行第一个操作就足够了。
在第三个示例中,除了[S2S3]之外,S的所有子字符串都是幸运的,因为我们不能对它和[S1S2S3](整个字符串)执行任何操作。
解题思路:
长度为m的二进制字符串T是幸运的,当且仅当m=1或(1<m和𝑆[𝑚]≠𝑆[𝑚−1])。
- 在S[m−1]=S[m]的情况下:我们永远不能删除最后两个字符,因为它们将始终保持相等。所以 S 不是幸运的。
- 在𝑆[𝑚−1]≠𝑆[𝑚]的情况下:如果m=2,我们可以通过一次操作达到我们的目标。否则,假设最后一个字符为0。现在最后三个字符不是010就是110。在第一种情况下,对[Sm−2,Sm−1]执行操作,在第二种情况下,对 [Sm−1,Sm] 执行操作。然后最后两个字符将是10,我们可以在新的字符串上继续这个算法,直到我们得到m=1。
长度为1的幸运的子字符串的个数等于n。为了计算更长的子字符串的个数,我们可以将索引2中的r固定为n。如果𝑆[𝑟]≠𝑆[𝑟−1]成立,我们应该在答案上加上r−1。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 9;
void solve()
{
int n; cin >> n;
ll ans = n;
string s; cin >> s;
for(int i = 1; i < n; ++i)
{
if(s[i] != s[i - 1]) ans += i;
}
cout << ans << '\n';
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int _; cin >> _;
while(_ --)solve();
return 0;
}
F:更短一点
题目描述
小小的也很可爱呢......
Piper有一串长度为n的二进制字符串s(即字符串只由0和1组成)。Piper觉得这串字符串不可爱,他想让它变得更可爱一点,但同时又希望它可爱地有内涵一点,所以Piper决定用一种特殊的方式让它变得可爱。
选择两个连续的字符si和si+1,如果si是1,si+1是0,他就可以擦除其中的1个字符(他可以选择擦除哪一个,但不能同时擦除两个字符)。擦除后字符串会更加地可爱!。
Piper可以进行任意数量的擦除(可能是零),他想让字符串s尽可能可爱。他认为对于两个不同的字符串x和y,短的字符串更可爱,如果它们的长度相同,那么从词典上看更小的字符串更可爱。
小提示:如果我们有两个长度相同的字符串x和y,那么如果有一个位置i是x1=y1、x2=y2、...、xi−1=yi−1和xi<yi,那么x在词法上比y小。
请打印Piper在操作过后能得到的最可爱的字符串。
输入描述
第一行包含整数t(1≤t≤104) - 测试用例数。
接下来的2t行包含测试用例--每两行一个。
每个测试用例的第一行包含整数n(1≤n≤105) - 字符串s的长度。
第二行包含二进制字符串s。字符串s是长度为n的字符串,仅由 0 和 1 组成。
保证测试用例中n的总和不超过105。
输出描述
打印t个答案--每个测试用例一个。
i-th 测试用例的答案是李在做了一定数量的操作(可能是零)后能得到的最可爱的字符串。
输入样例
5
10
0001111111
4
0101
8
11001101
10
1110000000
1
1
输出样例
0001111111
001
01
0
1
样例解释
在第一个测试用例中,Piper不用执行任何动作。
在第二个测试用例中,Piper应该擦除 s2 。
例如,在第三个测试用例中,Piper可以按照以下顺序下棋:11001101 →→ 1100101 →→ 110101 →→ 10101 →→ 1101 →→ 101 →→ 01。
解题思路:
已知我们无法对非降序的字符串进行操作。
操作的条件:前1后0。所以猜想:对于一串以1开头,以0结尾的子串都可以被擦除至剩一个0。
证明:
对于一串以1开头的字符串,从前往后删0,我们总能得到一串不包含0的字符串,这很容易。现在保留末尾的0,再从后往前删掉所有的1。显然是可取的。
于是我们得到结论,对于一串以1开头,以0结尾的子串都可以被擦除至剩一个0。而由于我们无法对非降序的字符串进行操作,所以答案的构成我们可以视作:
其中𝑆S为一串以1开头,以0结尾的子串。必然是这样的,如果在最前面加上一个1,那么不妨把中间子串的左边界扩至开头来保持结构;在末尾加0也是同理。
于是我们只要找第一个1,再找末尾一个0,将这两个位置及其中间的字符都替换为0即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 9;
void solve()
{
int n; cin >> n;
string s; cin >> s;
int l = -1, r = -1;
int flag = 1;
for(int i = 0; i < n; ++i)
{
if(s[i] == '1' && flag)
{
l = i;
flag = 0;
}
if(s[i] == '0' && !flag)
{
r = i;
}
}
if(l != -1 && r != -1)
{
for(int i = 0; i < l; ++i) cout << s[i];
for(int i = r; i < n; ++i) cout << s[i];
cout << '\n';
}
else cout << s << '\n';
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int _; cin >> _;
while(_ --)solve();
return 0;
}
最近动了个小手术,会停止更新一段时间,请谅解