c ++零基础可视化——字符串
string
定义:
string str1 = "012345"; // 012345
string str2 = str1; // 012345
string str3(6, '#'); // ######
string str4("012345"); // 012345
string str5(str1); // 012345
string str6(str1, 2); // 2345
string str7(str1, 2, 2); // 23
string str8("012345", 2); // 01
string str9({48, '1', '2'}); // 012
string str10(str1.begin() + 1, str1.end() - 1); // 1234
输入输出
string str;
cin >> str;
cout << str;
cin输入以空格分隔,若想输入整行,则用getline(cin, str)
操作
一些不熟知的用法:
printf("%s", str.c_str());
在string中除了可以用迭代器表示位置外,还可以直接用下标表示,所以有:
string str = "abc";
str.insert(1, "def");
// adefbc
在string的erase中,如果不填入删除的个数,只填入删除的位置,则默认将这个位置开始的后续字符全部删除,这与vector是不同的,注意区分。如:
string str1 = "adefbc";
str1.erase(1, 2);
// afbc
string str2 = "abfc";
str2.erase(1);
// a
append可将字符串加入末尾
string str = "a";
str.append("??bc");
// a??bc
replace相当于erase和insert的结合
string str = "a??bc";
str.replace(1, 2, "xyz");
// axyzbc
find
找子串并返回第一次出现的位置,也可规定起点开始查找。如果找不到,则返回string::npos
string str = "This is island";
int pos = str.find("is");
-> 2
*******************************
string str = "This is island";
int pos = str.find("is", 3);
-> 5
*******************************
string str = "This is island";
int pos = str.find("That");
-> string::npos
substr(),参数包含开始下标和长度。如果不写长度,则返回开始下标到结尾的字串
string str = "hello";
string sub = str.substr(2, 3); // llo
string sub1 = str.substr(1); // ello
starts_with(),ends_with() 前缀判断,后缀判断
string str = "hello";
bool res = str.starts_with("hel");
-> true
bool res1 = str.ends_with("llo");
->true;
常用普通函数
| 1 | 2 |
|---|---|
stoi() | 将字符串转为数字,类型为int |
stoll() | 将字符串转为数字,类型为long long |
stod() | 将字符串转为数字,类型为double |
to_string() | 将数字转为字符串,任意类型数字均可 |
format()可以构造string
https://www.luogu.com.cn/problem/B3713
[语言月赛202302] 对了,还有花,少女,银河
题目背景
扶苏是洛谷网校的一名讲师,她负责了一场基础-提高衔接计划全真模拟赛。
在全真模拟赛里,需要选手在本地完成代码后按照真实比赛的要求放入以题目名命名的子目录(子文件夹)中,子文件夹的上级文件必须是用考号命名的文件夹。再把用考号命名的文件夹打成 zip。
例如,如果一道题目的名字叫做 ovo,那么源程序必须命名为 ovo.cpp。如果选手考号为 SD-114,那么从 zip 起本题的目录结构必须为:
SD-114.zip/SD-114/ovo/ovo.cpp
这里 / 符号表示的是两级目录之间的间隔。
如果该选手的目录结构变成了 SD-114.zip/SD-114/SD-114/ovo/ovo.cpp(也就是套了两层用考号名命名的文件夹),将无法正常评测。
题目描述
但是,扶苏生气地发现,即使在前一天晚上已经在群里强调了多次如何打包,并且通过测试赛指出了提交文件目录有问题的选手,但在全真模拟赛时仍有大量同学的目录结构出现问题。
一共有 n n n 名选手参加全真模拟赛,模拟赛共 m m m 道题。给出每道题的名字和每个选手每份源程序的目录结构,请你对于每个选手的每份源程序,判定 ta 的源程序目录是否正确。
选手的错误五花八门,包括但不限于:源程序名写错、考号写错、文件夹套多等等问题。为了方便起见,我们约定对于考号为 X 的选手的题目 Y,X.zip/X/Y/Y.cpp 是唯一正确的目录结构,其余结构均为错误结构。
注意:同一选手不同题目的上级目录可能是不同的,也可能一个正确一个错误。
输入格式
第一行是两个整数,依次表示参赛选手数
n
n
n 和题目数
m
m
m。
接下来
m
m
m 行,每行一个字符串
s
i
s_i
si,表示一道题目的名字。
接下来
(
m
+
1
)
×
n
(m+1) \times n
(m+1)×n 行,每
(
m
+
1
)
(m+1)
(m+1) 行一组表示一名选手的所有题目的目录结构:
每组第一行是一个字符串
t
i
t_i
ti,表示该选手的考号。
接下来
m
m
m 行,每行一个字符串
r
i
r_i
ri,按题目顺序给出该选手每道题目的目录结构。
输出格式
按输入顺序,对每个选手的每个目录结构,输出一行一个字符串,如果该选手的目录结构正确,输出 Fusu is happy!,否则输出 Fusu is angry!。
样例 #1
样例输入 #1
4 2
ovo
vov
SD-114
SD-114.zip/SD-114/ovo/ovo.cpp
SD-114.zip/SD114/vov/vov.cpp
LG-514
LG-514.zip/lg-514/ovo/ovo.cpp
LG-514.zip/LG-514/vov/ovo.cpp
PJ-998
PJ-998.zip/PJ-998/PJ-998/ovo/ovo.cpp
PJ-998/PJ-998/vov/vov.cpp
fusu
fusu.zip/fusu/ovo/ovo.cpp
fusu.zip/fusu/ovo/vov.cpp
样例输出 #1
Fusu is happy!
Fusu is angry!
Fusu is angry!
Fusu is angry!
Fusu is angry!
Fusu is angry!
Fusu is happy!
Fusu is angry!
提示
样例 1 解释
共有
4
4
4 位选手,
2
2
2 道题目。两道题目分别是 ovo 和 vov。
- 第一位选手的准考证号是
SD-114。 -
- 他的第一题目录完全正确。
-
- 他第二题的第二级目录(SD114 文件夹)没有加中间的
-符号,与准考证号不一致,故错误。
- 他第二题的第二级目录(SD114 文件夹)没有加中间的
- 第二位选手的准考证号是
LG-514。 -
- 他第一题的第二级目录使用了小写字母,错误。
-
- 他第二题的源程序名写成了
ovo.cpp,应该是vov.cpp,错误
- 他第二题的源程序名写成了
- 第三位选手的准考证号是
PJ-998。 -
- 他第一题的的准考证号目录套了两层(即有两个
PJ-998),故错误。
- 他第一题的的准考证号目录套了两层(即有两个
-
- 他第二题没有打 zip 包(第一级目录没有
.zip后缀),故错误
- 他第二题没有打 zip 包(第一级目录没有
- 第四位选手的准考证号是
fusu。 -
- 她第一题的目录完全正确。
-
- 她第二题的子目录(第三级目录)写成了
ovo,因该是vov,故错误。
- 她第二题的子目录(第三级目录)写成了
数据规模与约定
- 对 30 % 30\% 30% 的数据, n = 1 n = 1 n=1。
- 另有 30 % 30\% 30% 的数据, m = 1 m = 1 m=1。
- 对
100
%
100\%
100% 的数据,
1
≤
n
,
m
≤
10
1 \leq n,m\leq 10
1≤n,m≤10,
s
i
s_i
si 和
t
i
t_i
ti 的长度均不超过
20
20
20,
r
i
r_i
ri 的长度不超过
500
500
500。字符串均只含大小写字母、数字和
-,.与/符号。保证题目名和准考证号不含/符号。
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
#define endl "\n"
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int n, m;
cin >> n >> m;
vector<string> name(m);
for(auto& x : name) cin >> x;
for(int i = 0; i < n; i ++) {
string number;
cin >> number;
//SD-114.zip/SD-114/ovo/ovo.cpp
for(int j = 0; j < m; j ++) {
string str;
cin >> str;
string correct = format("{0}.zip/{0}/{1}/{1}.cpp", number, name[j]);
if(str == correct) {
cout << "Fusu is happy!" << endl;
} else {
cout << "Fusu is angry!" << endl;
}
}
}
return 0;
}
启发:可以利用format很好的构造字符串!!!
https://www.luogu.com.cn/problem/B3976
[语言月赛 202405] 交题解
题目描述
小 S 想要在 Luogu 上提交一篇非常美妙的题解,但是小 Q 不希望看到小 S 的题解比自己的点赞更多,于是她故意在小 S 的题解中加入了一些奇怪的字符。
具体来说,原本的题解可以看作一个只包含小写或大写字母的字符串 S S S,而小 Q 在其中若干位置插入了一些随机字符,这些字符可能是数字或标点符号,但一定不是字母,且一定在键盘上出现。我们称被添加字符后的字符串为 S ′ S' S′。
你的任务是,将 S ′ S' S′ 中非大小写字母的字符全部去除,然后将得到的字符串输出。
输入格式
输入仅一行,一个字符串 S ′ S' S′,表示被添加字符后的字符串。
输出格式
输出仅一行,一个字符串 S S S,表示原字符串。
样例 #1
样例输入 #1
I*Love*Luogu**333#$$
样例输出 #1
ILoveLuogu
样例 #2
样例输入 #2
L2u4o6gu##$%Lov()es^me
样例输出 #2
LuoguLovesme
样例 #3
样例输入 #3
[]{}->%_;'pxprpx
样例输出 #3
pxprpx
提示
样例 1 解释
在字符串 I*Love*Luogu**333#$$ 中,字符 *,#,$ 属于标点符号,字符 3 属于数字,这些都是后添加的字符。删除后,字符串变为 ILoveLuogu。
样例 2 解释
在字符串 L2u4o6gu##$%Lov()es^me 中,字符 #,$,%,(,),^,` 属于标点符号,字符 2,4,6 属于数字,这些都是后添加的字符。删除后,字符串变为 LuoguLovesme。
数据范围
对于前
30
%
30 \%
30% 的数据,保证
S
′
S'
S′ 中只包含拉丁字母。
对于另
30
%
30 \%
30% 的数据,保证
S
′
S'
S′ 中只包含拉丁字母和下划线 _。
对于
100
%
100 \%
100% 的数据,保证
S
′
S'
S′ 的长度在
1
1
1 到
1
0
6
10^6
106 之间,
S
′
S'
S′ 中只出现键盘上主键盘区中的字母、标点符号、数字,不含空格、换行符等结束符号。
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
#define endl "\n"
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
string str;
cin >> str;
string ans;
for(auto& x : str) {
if(isalpha(x)) ans.push_back(x);
}
cout << ans << endl;
return 0;
}
启发:isalpha()的用法。
https://www.luogu.com.cn/problem/B2123
字符串 p 型编码
题目描述
给定一个完全由数字字符(‘0’,‘1’,‘2’,…,‘9’)构成的字符串 str ,请写出 str 的 p 型编码串。例如:字符串 122344111 可被描述为 1个1、2个2、1个3、2个4、3个1 ,因此我们说122344111 的 p 型编码串为 1122132431 ;类似的道理,编码串 101 可以用来描述 1111111111 ;00000000000 可描述为 11个0,因此它的p型编码串即为 110 ;100200300 可描述为 1个1、2个 0、1个2、2个0、1个3、2个0,因此它的 p 型编码串为 112012201320。
输入格式
输入仅一行,包含字符串 str。每一行字符串最多包含 1000 1000 1000 个数字字符。
输出格式
输出该字符串对应的 p p p 型编码串。
样例 #1
样例输入 #1
122344111
样例输出 #1
1122132431
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
#define endl "\n"
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
string str;
cin >> str;
string res;
char lastChar = str[0];
int len = 1;
for(int i = 1; i <= str.size(); i ++) {
if(str[i] == lastChar) {
len ++;
} else {
res += to_string(len) + lastChar;
lastChar = str[i];
len = 1;
}
}
cout << res << endl;
return 0;
}
启发:将一个字符串分组,将相同的字符提取出来是很常见的操作。做法是:
char lastChar = str[0];
int len = 1;
for(int i = 1; i <= str.size(); i ++) {
if(str[i] == lastChar) {
len ++;
} else {
res += to_string(len) + lastChar;
lastChar = str[i];
len = 1;
}
}
其中尤为注意for循环中的条件是 i <= str.size()。若为i < str.size(),则最后的字符不会被考虑。
https://www.luogu.com.cn/problem/B3663
[语言月赛202209] Luogu Academic
题目描述
七海在 LA 群中游走,获得了一个由英文小写字符组成的字符串 S S S。
七海想要知道,子串 luogu 在其中出现了多少次。
提示: 一个字符串中,任意连续的字符构成的子字符串称为子串。
例如,字符串 abc 一共包含 7 个子串,分别为:空串(不包含任何字符),a,ab,abc,b,bc,c。注意,字符串 ac 不是 abc 的子串。
输入格式
输入一行一个字符串 S S S。
输出格式
输出一行一个整数,代表子串 luogu 在字符串
S
S
S 中出现的次数。
样例 #1
样例输入 #1
luoluoguluogu
样例输出 #1
2
提示
对于
30
%
30\%
30% 的数据,
∣
S
∣
<
5
|S| < 5
∣S∣<5;
对于另外
30
%
30\%
30% 的数据,字符串
S
S
S 仅由以下四个字符 l,u,o,g 组成;
对于
100
%
100\%
100% 的数据,
1
≤
∣
S
∣
≤
1
0
6
1 \le |S| \le 10^6
1≤∣S∣≤106,保证字符串仅由小写英文字母组成。
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
#define endl "\n"
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
string str;
cin >> str;
int cnt = 0;
int idx = str.find("luogu");
while(idx != string::npos) {
cnt ++;
idx = str.find("luogu", idx + 1);
}
cout << cnt << endl;
return 0;
}
启发:find的用法。其中find的第二个参数可以规定从哪个下标为起点开始查找。
https://www.luogu.com.cn/problem/B3997
[洛谷 202406GESP 模拟 三级] 小洛的字符串分割
题目描述
对于一个字符串 S S S,小洛定义它为 回文 的,当且仅当字符串 S S S 从左往右读和从右往左读一样,例如 a b c b a \tt abcba abcba 是回文的,而 a b c c a \tt abcca abcca 不是。
小洛现在有一个字符串 S S S,他想将这个字符串分为若干段,段长度分别为 1 , 2 , 3 , … 1,2,3,\dots 1,2,3,…。具体而言,他会先将第一个字符拿出来作为字符串 S 1 S_1 S1,再将第 2 , 3 2,3 2,3 个字符拿出来作为 S 2 S_2 S2,再将第 4 , 5 , 6 4,5,6 4,5,6 个字符拿出来作为 S 3 S_3 S3,以此类推……最后若还有多余的字符,则单独作为一段。
例如说,对于字符串 a a a b a b c a a c d \tt aaababcaacd aaababcaacd,会被分为如下的五个字符串:
- S 1 = a S_1=\tt a S1=a;
- S 2 = a a S_2=\tt aa S2=aa;
- S 3 = b a b S_3=\tt bab S3=bab;
- S 4 = c a a c S_4=\tt caac S4=caac;
- S 5 = d S_5=\tt d S5=d;
字符串 a a a b a b c a a c d \tt aaababcaacd aaababcaacd 分割出的 5 5 5 个字符串都是回文的。
小洛想要知道,对于读入的字符串 S S S,这些被分割出来的字符串,有多少个是回文的呢?
输入格式
输入一行,一个字符串 S S S。
输出格式
输出一个整数,表示答案。
样例 #1
样例输入 #1
aaababcaacd
样例输出 #1
5
样例 #2
样例输入 #2
abacdcaaba
样例输出 #2
2
提示
【样例解释】
- 对于第 1 1 1 组样例,已经在题面中进行表述;
- 对于第 2 2 2 组样例, S 1 = a S_1=\tt a S1=a, S 2 = b a S_2=\tt ba S2=ba, S 3 = c d c S_3=\tt cdc S3=cdc, S 4 = a a b a S_4=\tt aaba S4=aaba,其中 S 1 S_1 S1 与 S 3 S_3 S3 为回文字符串。
【数据范围】
假定记号 ∣ S ∣ |S| ∣S∣ 表示字符串 S S S 的长度。
-
对于 10 % 10\% 10% 的数据,字符串至多包含一种字母;
-
对于 30 % 30\% 30% 的数据,字符串至多包含两种字母;
-
对于 70 % 70\% 70% 的数据, ∣ S ∣ ≤ 1000 |S|\leq 1000 ∣S∣≤1000;
-
对于所有数据, 1 ≤ ∣ S ∣ ≤ 1 0 6 1 \leq |S| \leq 10^6 1≤∣S∣≤106,字符串仅包含英语小写字母。
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
#define endl "\n"
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
string str;
cin >> str;
auto f = [&](string str) -> bool {
string temp = str;
reverse(str.begin(), str.end());
return temp == str;
};
int idx = 0, len = 1;
int res = 0;
while(idx < str.size()) {
string subStr = str.substr(idx, len);
idx += len;
len ++;
if(f(subStr)) res ++;
}
cout << res << endl;
return 0;
}
启发:对于这种操作不要想的太复杂。可以轻松解决问题。
idx += len; len ++;
https://www.luogu.com.cn/problem/B3726
[语言月赛202303] String Problem P
题目描述
Farmer John 有 n n n 个字符串,第 i i i 个字符串为 s i s_i si。
现在,你需要支持如下 q q q 次操作:
1 x y i:把字符串 s x s_x sx 整体插入到字符串 s y s_y sy 的第 i i i 个字符后,更新 s y s_y sy。2 y:求 s y s_y sy。
例如,设
s
1
=
abc
s_1 = \texttt{abc}
s1=abc,
s
2
=
xyz
s_2 = \texttt{xyz}
s2=xyz,则执行完 1 2 1 2 后(把
s
2
s_2
s2 整体插入到
s
1
s_1
s1 的第
2
2
2 个字符后,更新
s
1
s_1
s1),
s
1
=
abxyzc
s_1 = \texttt{abxyzc}
s1=abxyzc,
s
2
=
xyz
s_2 = \texttt{xyz}
s2=xyz。
输入格式
第一行是两个整数,表示字符串数量
n
n
n 和操作的数量
q
q
q。
接下来
n
n
n 行,每行一个字符串,第
i
i
i 行的字符串为
s
i
s_i
si。
接下来
q
q
q 行,每行四个或二个整数,依次表示每次操作。具体格式见『题目描述』。
输出格式
对每次操作 2 2 2,输出一行一个字符串,表示被询问的串。
样例 #1
样例输入 #1
2 2
a
b
1 1 2 1
2 2
样例输出 #1
ba
样例 #2
样例输入 #2
3 6
abc
ijk
xyz
1 2 3 2
1 1 3 5
1 3 1 1
2 1
2 2
2 3
样例输出 #2
axyijkabczbc
ijk
xyijkabcz
提示
数据规模与约定
- 对 60 % 60\% 60% 的数据,保证 i = ∣ s y ∣ i = |s_y| i=∣sy∣。
- 对 100 % 100\% 100% 的数据, 1 ≤ n , q ≤ 10 1 \leq n,q \leq 10 1≤n,q≤10, 1 ≤ ∣ s i ∣ ≤ 10 1 \leq |s_i| \leq 10 1≤∣si∣≤10。 1 ≤ x , y ≤ n 1 \leq x, y \leq n 1≤x,y≤n, 1 ≤ i ≤ ∣ s y ∣ 1 \leq i \leq |s_y| 1≤i≤∣sy∣。
其中 ∣ s y ∣ |s_y| ∣sy∣ 表示进行对应操作时 s y s_y sy 的长度, ∣ s i ∣ |s_i| ∣si∣ 表示输入时字符串的长度。
provider:一扶苏一
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
#define endl "\n"
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int n, q;
cin >> n >> q;
vector<string> str(n + 1);
for(int i = 1; i <= n; i ++) {
cin >> str[i];
}
for(int i = 0; i < q; i ++) {
int op;
cin >> op;
if(op == 1) {
int x, y, i;
cin >> x >> y >> i;
str[y].insert(i, str[x]);
}
if(op == 2) {
int y;
cin >> y;
cout << str[y] << endl;
}
}
return 0;
}
启发:按题意操作即可。
https://www.luogu.com.cn/problem/B3769
[语言月赛202305] 制糊串
题目背景
在这个问题中,我们用 s [ x , y ] s[x,y] s[x,y] 表示从字符串 s s s 的第 x x x 个字符到第 y y y 个字符连起来构成的字符串。例如,若 s = abcdef s = \texttt{abcdef} s=abcdef,则 s [ 2 , 4 ] = bcd s[2,4] = \texttt{bcd} s[2,4]=bcd。
题目描述
给出两个字符串 s s s 和 t t t,有 q q q 次询问。
每次给出 l 1 , r 1 l_1, r_1 l1,r1 和 l 2 , r 2 l_2, r_2 l2,r2,请判断 s [ l 1 , r 1 ] s[l_1, r_1] s[l1,r1] 和 t [ l 2 , r 2 ] t[l_2, r_2] t[l2,r2] 谁的字典序更小。
输入格式
第一行是一个字符串
s
s
s。
第二行是一个字符串
t
t
t。
第三行是一个整数,表示询问次数
q
q
q。
接下来
q
q
q 行,每行四个整数
l
1
,
r
1
,
l
2
,
r
2
l_1, r_1, l_2, r_2
l1,r1,l2,r2,表示一次询问。
输出格式
对每次询问,输出一行一个字符串:
- 如果 s [ l 1 , r 1 ] s[l_1, r_1] s[l1,r1] 的字典序更小,请输出 yifusuyi \texttt{yifusuyi} yifusuyi。
- 如果 t [ l 2 , r 2 ] t[l_2, r_2] t[l2,r2] 的字典序更小,请输出 erfusuer \texttt{erfusuer} erfusuer。
- 如果两者的字典序一样大,请输出 ovo \texttt{ovo} ovo。
样例 #1
样例输入 #1
Yifusuyi
yifusuYi
3
1 2 7 8
1 2 1 2
7 8 7 8
样例输出 #1
ovo
yifusuyi
erfusuer
提示
数据规模与约定
以下用 ∣ s ∣ |s| ∣s∣ 表示 s s s 的长度, ∣ t ∣ |t| ∣t∣ 表示 t t t 的长度。
- 对 30 % 30\% 30% 的数据, ∣ s ∣ = ∣ t ∣ = 1 |s| = |t| = 1 ∣s∣=∣t∣=1。
- 对 60 % 60\% 60% 的数据, q = 1 q = 1 q=1。
- 对 100 % 100\% 100% 的数据, 1 ≤ ∣ s ∣ , ∣ t ∣ , q ≤ 1 0 3 1 \leq |s|, |t|, q \leq 10^3 1≤∣s∣,∣t∣,q≤103, 1 ≤ l 1 ≤ r 1 ≤ ∣ s ∣ 1 \leq l_1 \leq r_1 \leq |s| 1≤l1≤r1≤∣s∣, 1 ≤ l 2 ≤ r 2 ≤ ∣ t ∣ 1 \leq l_2 \leq r_2 \leq |t| 1≤l2≤r2≤∣t∣。输入字符串仅含大小写英文字母。
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
#define endl "\n"
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
string str1, str2;
cin >> str1 >> str2;
int q;
cin >> q;
while(q --) {
int l1, r1, l2, r2;
cin >> l1 >> r1 >> l2 >> r2;
string t1, t2;
t1 = str1.substr(l1 - 1, r1 - l1 + 1);
t2 = str2.substr(l2 - 1, r2 - l2 + 1);
auto order = t1 <=> t2;
if(order < 0) {
cout << "yifusuyi" << endl;
} else if(order > 0) {
cout << "erfusuer" << endl;
} else {
cout << "ovo" << endl;
}
}
return 0;
}
启发:字符串的比较性能较差,可以使用三路运算符,可以很好的优化多次比较。
https://www.luogu.com.cn/problem/B3892
[语言月赛 202311] 方程求解
题目描述
小 A 有 n n n 个关于 x x x 的方程,第 i i i 个方程形如 a i x i + b i = c i a_ix_i+b_i=c_i aixi+bi=ci。方程的解 x x x 均为正整数,例如下面几个方程都是符合要求的方程:
2x+4=10
-3x+13=10
4x-8=16
其中,第一组方程的解为 x 1 = 3 x_1=3 x1=3,第二组方程的解为 x 2 = 1 x_2=1 x2=1,第三组方程的解为 x 3 = 6 x_3=6 x3=6。
小 A 想要知道,给定 L , R L,R L,R,在 L ≤ x ≤ R L\leq x\leq R L≤x≤R 的范围内,有多少个正整数 x x x 满足 x x x 是其中至少一个方程的解。为了防止你欺骗他,他会询问你 Q Q Q 次。
输入格式
第一行输入两个正整数 n , Q n,Q n,Q,分别表示小 A 有的方程数,以及小 A 想要向你询问的次数。
第二行开始,往下 n n n 行,每行一个字符串,描述一个方程。
第 ( n + 2 ) (n+2) (n+2) 行开始,往下 Q Q Q 行,每行两个正整数 L , R L,R L,R,表示一次询问,即给定 L , R L,R L,R,询问在 L ≤ x ≤ R L\leq x\leq R L≤x≤R 的范围内,有多少个正整数 x x x 满足 x x x 是其中至少一个方程的解。
输出格式
对于每次询问,输出一行一个整数,表示有多少个在 L ≤ x ≤ R L\leq x\leq R L≤x≤R 的范围内的正整数 x x x,满足 x x x 是其中至少一个方程的解。
样例 #1
样例输入 #1
3 4
2x+4=10
-3x+13=10
4x-8=16
1 6
1 8
3 6
4 5
样例输出 #1
3
3
2
0
样例 #2
样例输入 #2
5 3
5x-2=13
8x+5=45
4x-12=8
-2x+10=4
3x-7=2
1 3
1 5
3 5
样例输出 #2
1
2
2
提示
【样例解释】
对于第一组样例,即为题目中的举例。三组方程的解分别为 x 1 = 3 , x 2 = 1 , x 3 = 6 x_1=3,x_2=1,x_3=6 x1=3,x2=1,x3=6。则:
- 对于 1 ≤ x ≤ 6 1\leq x\leq 6 1≤x≤6 的范围,有 3 3 3 个 x x x 的取值( x = 1 , 3 , 6 x=1,3,6 x=1,3,6)是其中至少一个方程的解;
- 对于 1 ≤ x ≤ 8 1\leq x\leq 8 1≤x≤8 的范围,同上所述;
- 对于 3 ≤ x ≤ 6 3\leq x\leq 6 3≤x≤6 的范围,有 2 2 2 个 x x x 的取值( x = 3 , 6 x=3,6 x=3,6)是其中至少一个方程的解;
- 对于 4 ≤ x ≤ 5 4\leq x\leq 5 4≤x≤5 的范围,不存在一个 x x x 是其中至少一个方程的解;
- 因此分别输出 3 , 3 , 2 , 0 3,3,2,0 3,3,2,0。
对于第二组样例,五组方程的解分别为 x 1 = 3 , x 2 = 5 , x 3 = 5 , x 4 = 3 , x 5 = 3 x_1=3,x_2=5,x_3=5,x_4=3,x_5=3 x1=3,x2=5,x3=5,x4=3,x5=3。则:
- 对于 1 ≤ x ≤ 3 1\leq x\leq 3 1≤x≤3 的范围,只有 x = 3 x=3 x=3 满足是其中至少一个方程的解;
- 对于 1 ≤ x ≤ 5 1\leq x\leq 5 1≤x≤5 的范围,有 2 2 2 个 x x x 的取值( x = 3 , 5 x=3,5 x=3,5)是其中至少一个方程的解;
- 对于 3 ≤ x ≤ 5 3\leq x\leq 5 3≤x≤5 的范围,有 2 2 2 个 x x x 的取值( x = 3 , 5 x=3,5 x=3,5)是其中至少一个方程的解;
- 因此分别输出 1 , 2 , 2 1,2,2 1,2,2。
【数据范围】
数据保证, 1 ≤ n , Q ≤ 1000 1\leq n,Q\leq 1000 1≤n,Q≤1000,方程中 a i , b i , c i a_i,b_i,c_i ai,bi,ci 满足 1 ≤ ∣ a i ∣ , ∣ b i ∣ , ∣ c i ∣ ≤ 2000 1 \leq |a_i|,|b_i|,|c_i| \leq 2000 1≤∣ai∣,∣bi∣,∣ci∣≤2000,每一组方程的解 x i x_i xi 必定为正整数。询问时的 L , R L,R L,R 满足 1 ≤ L ≤ R ≤ 1000 1\leq L\leq R\leq 1000 1≤L≤R≤1000。
本题前八个测试点每个测试点 8 分,后四个测试点每个测试点 9 分。
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
#define endl "\n"
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, q;
cin >> n >> q;
map<int, int> hash;
for(int i = 0; i < n; i ++) {
int a, b, c;
char x, op, eq;
cin >> a >> x >> op >> b >> eq >> c;
if(op == '+') {
hash[(c - b) / a] ++;
} else {
hash[(c + b) / a] ++;
}
}
for(int i = 0; i < q; i ++) {
int l, r, cnt = 0;
cin >> l >> r;
for(auto& [u, v] : hash) {
if(u > r) break;
if(u >= l && u <= r) {
cnt ++;
}
}
cout << cnt << endl;
}
return 0;
}
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
#define endl "\n"
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, q;
cin >> n >> q;
vector<int> a, b, c;
for(int i = 0; i < n; i ++) {
string str;
cin >> str;
int idxX = str.find("x");
int idxEq = str.find("=");
a.push_back(stoi(str.substr(0, idxX)));
b.push_back(stoi(str.substr(idxX + 1, idxEq - idxX)));
c.push_back(stoi(str.substr(idxEq + 1)));
}
for(int i = 0; i < q; i ++) {
int l, r;
cin >> l >> r;
int cnt = 0;
for(int k = l; k <= r; k ++) {
for(int idx = 0; idx < a.size(); idx ++) {
if(a[idx] * k + b[idx] == c[idx]) {
cnt ++;
break;
}
}
}
cout << cnt << endl;
}
return 0;
}
启发:主要是各种操作。要加强对substr(),find(),stoi()等等的掌握。
https://www.luogu.com.cn/problem/B3911
[语言月赛 202312] 铅球杯
题目描述
蓝边铅球组织了“铅球杯”数据标注大赛。为了实现 Au 大满贯的宏大征途,LeAuingZ 报名参加了比赛。
蓝边铅球给出了
N
N
N 个 int 类型变量的名字及其值,并要求 LeAuingZ 对
k
k
k 句话进行数据标注。每句话由大小写英文字母、空格、半角逗号、半角句号和 {、} 组成。在 {} 之间的,为
N
N
N 个变量名中的一个,LeAuingZ 需要将每一句话中全部的 {变量名} 替换为变量的值并输出。
例如,有
a
=
3
,
b
=
4
a=3,b=4
a=3,b=4,对于句子 We know a is {a}, b is {b}.,替换后将得到 We know a is 3, b is 4.。
LeAuingZ 觉得这个任务很无聊,决定编写一个程序来快速获得 Au。
输入格式
输入共 N + k + 1 N+k+1 N+k+1 行。
输入的第一行为两个整数 N , k N,k N,k。
接下来 N N N 行,每行一个小写英文字符串、一个整数,分别代表变量名和变量的值。
接下来 k k k 行,每行一个需要标注的句子。
输出格式
输出 k k k 行,每行一个标注好的句子。
样例 #1
样例输入 #1
5 2
abc 1
a 2
b 3
c 4
d 5
We have {a} apples.
We {d}onot have pencils.
样例输出 #1
We have 2 apples.
We 5onot have pencils.
提示
-
对于 20 % 20\% 20% 的测试数据, k = 1 k=1 k=1。
-
对于另外 30 % 30\% 30% 的测试数据, 1 ≤ N ≤ 26 1 \le N \le 26 1≤N≤26,变量名长度均为 1 1 1。
-
对于 100 % 100\% 100% 的测试数据, 1 ≤ N ≤ 5000 1 \le N \le 5000 1≤N≤5000, 1 ≤ k ≤ 20 1 \le k \le 20 1≤k≤20。变量名仅含英文小写字母,变量名长度不超过 20 20 20,变量的值在 int 范围内,标注前句子长度不超过 5 × 1 0 4 5 \times 10^4 5×104,保证
{}成对合法出现。每句话由大小写英文字母、空格、半角逗号、半角句号和{、}组成。
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
#define endl "\n"
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, k;
cin >> n >> k;
map<string, int> hash;
for(int i = 0; i < n; i ++) {
string s;
int a;
cin >> s >> a;
hash[s] = a;
}
string str;
getline(cin, str);
for(int i = 0; i < k; i ++) {
getline(cin, str);
int idxL = str.find("{");
while(idxL != string::npos) {
int idxR = str.find("}");
string value = str.substr(idxL + 1, idxR - idxL - 1);
str.replace(idxL, idxR - idxL + 1, to_string(hash[value]));
idxL = str.find("{", idxL + 1);
}
cout << str << endl;
}
return 0;
}
启发:综合使用各种操作函数,需要熟练掌握。
其中以输入样例为例,注意到,要先读取句子上面的换行符,才可以成功读取两个句子。

1122

被折叠的 条评论
为什么被折叠?



