2024.2.29|华北水利水电大学江淮校区ACM社团训练赛
1.[NOIP2005]校门外的树
2.[NOIP2010]数字统计
3.[NOIP2013]记数问题
4.[NOIP2018]标题统计
5.字符串排序(1)
6.判断闰年
7.老子的全排列呢
8.[NOIP1998]拼数
心有猛虎,细嗅蔷薇。你好朋友,这里是锅巴的C\C++学习笔记,常言道,不积跬步无以至千里,希望有朝一日我们积累的滴水可以击穿顽石。
[NOIP2005]校门外的树
题目:
某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米。我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置;数轴上的每个整数点,即0,1,2,……,L,都种有一棵树。
由于马路上有一些区域要用来建地铁。这些区域用它们在数轴上的起始点和终止点表示。已知任一区域的起始点和终止点的坐标都是整数,区域之间可能有重合的部分。现在要把这些区域中的树(包括区域端点处的两棵树)移走。你的任务是计算将这些树都移走后,马路上还有多少棵树。
输入描述:
第一行有两个整数:L(1 <= L <= 10000)和 M(1 <= M <= 100),L代表马路的长度,M代表区域的数目,L和M之间用一个空格隔开。接下来的M行每行包含两个不同的整数,用一个空格隔开,表示一个区域的起始点和终止点的坐标。
输出描述:
包括一行,这一行只包含一个整数,表示马路上剩余的树的数目。
示例1
输入
500 3
150 300
100 200
470 471
输出
298
备注:
对于20%的数据,区域之间没有重合的部分;
对于其它的数据,区域之间有重合的情况。
注意:
主要考察差分和枚举。
实践代码:
void solve(){
int l,m,num = 0;cin>>l>>m;
vector<int> a(l+1);//定义一个数组代表马路,数组元素代表彼此相邻为1米的树
for(int i=0;i<=l;i++) a[i]=1;//数组中的元素都初始化为1,代表此处有树
while(m--){
int c,d;cin>>c>>d;
for(int i=c;i<=d;i++) a[i]=0;//区域中数组置0,代表此处树被移走
}
for(int i=0;i<=l;i++){
if(a[i]==1) num++;//此时数组元素为1的总数即为所剩余树的数目
}
cout<<num;
}
[NOIP2010]数字统计
题目:
请统计某个给定范围[L, R]的所有整数中,数字2出现的次数。
比如给定范围[2, 22],数字2在数2中出现了1次,在数12中出现1次,在数20中出现1次,在数21中出现1次,在数22中出现2次,所以数字2在该范围内一共出现了6次。
输入描述:
输入共1行,为两个正整数L和R,之间用一个空格隔开。
输出描述:
输出共1行,表示数字2出现的次数。
示例1
输入
2 22
输出
6
示例2
输入
2 100
输出
20
备注:
1≤L≤R≤10000
注意:
题目中问范围内2出现的次数(设为num=0),且已知本题范围不大(1,10000),那我们就可以暴力枚举每一位上的数字,即用x%10,判断是否为2,是了就记录num++,不是就不加,每次判断完就x/10,直至判断到x的最大一位数结束(此时x/=10,x会等于0,自动跳出循环)。
实践代码:
void solve(){
int l,r,num=0,i;cin>>l>>r;
for(i=l;i<=r;i++){
int x = i;
//关键的三行代码:
while(x){
if(x%10==2) num++;
x/=10;
}
}
cout<<num;
}
扩展:
[NOIP2013]记数问题
题目:
试计算在区间1 到n 的所有整数中,数字x(0 ≤ x ≤ 9)共出现了多少次?
例如,在1到11 中,即在1、2、3、4、5、6、7、8、9、10、11 中,数字1 出现了4 次。
输入描述:
输入共1行,包含2个整数n、x,之间用一个空格隔开。
输出描述:
输出共1行,包含一个整数,表示x出现的次数。
示例1
输入
11 1
输出
4
备注:
对于100%的数据,1≤ n ≤ 1,000,000,0 ≤ x ≤ 9。
注意:
细心的朋友一定会发现,本题即在“数字统计”题的基础上将2换成了x,所以照葫芦画瓢您一定会吧。
实践代码:
void solve(){
int n,x,num=0;cin>>n>>x;
for(int i =1;i<=n;i++){
int y = i;
while(y){
if(y%10==x) num++;
y/=10;
}
}
cout<<num;
}
[NOIP2018]标题统计
题目:
凯刚写了一篇美妙的作文,请问这篇作文的标题中有多少个字符?
注意:标题中可能包含大、小写英文字母、数字字符、空格和换行符。统计标题字 符数时,空格和换行符不计算在内。
输入描述:
输入文件只有一行, 一个字符串s。
输出描述:
输出文件只有一行,包含一个整数,即作文标题的字符数(不含空格和换行符)。
示例1
输入
234
输出
3
说明
标题中共有 3 个字符,这 3 个字符都是数字字符。
示例2
输入
Ca 45
输出
4
说明
标题中共有 5 个字符,包括 1 个大写英文字母,1 个小写英文字母和 2 个数字字符,
还有 1 个空格。由于空格不计入结果中,故标题的有效字符数为 4 个。
备注:
规定|s|表示字符串s的长度(即字符串中的字符串中的字符和空格数)。
对于40%的数据,1≤|s|≤5,保证输入为数字符及行末换符。
对于80%的数据,1≤|s|≤5,输入只可能包含大、小写英文字母大、小写英文字母、数字符及行末换符。
对于100%的数据,1≤|s|≤5,输入可能包含大,输入可能包含大、小写英文字母写英文字母、数字符、空格和行末换符。
注意:
常识:cin和scanf处理输入时遇到空格自动停止,所以其实本题考察一个特别简单的函数getline( )
的使用。
补充:
getline()
:成员函数getline()是从输入流中读取一行字符,读到终止符时会将’\0’存入结果缓冲区中 [4],作为输入的终止。
C++中最经典的一种getline()函数用法是:
string s;
getline(cin,s);
实践代码:
void solve(){
string s;getline(cin,s);
int c=0;
for(int i=0;i<s.size();i++){
if(s[i]!=' ') c++;
}
cout<<c;
}
字符串排序(1)
题目:
对输入的字符串进行排序后输出
输入描述:
输入有两行,第一行n
第二行是n个字符串,字符串之间用空格隔开
输出描述:
输出一行排序后的字符串,空格隔开,无结尾空格
示例1
输入
5
c d a bb e
输出
a bb c d e
注意:
sort()对字符串类型数组默认按字典序排序!
实践代码:
void solve(){
int n;cin>>n;
vector<string> a;
for(int i=0;i<n;i++){
string s;cin>>s;
a.push_back(s);
}
sort(a.begin(),a.end());
for(auto ele:a){//加强for
cout<<ele<<' ';
}
}
判断闰年
题目:
判断一个整数n是否是闰年
输入描述:
输入一个整数n (1≤n≤2018)
输出描述:
是闰年输出"yes" 否则输出"no"
示例1
输入
2000
输出
yes
示例2
输入
1900
输出
no
注意:
常识:闰年即只有能被400整除的年份才是世纪闰年!
实践代码:
void solve(){
int n;cin>>n;
if(n%400==0) cout<<"yes";
else cout<<"no";
}
老子的全排列呢
题目:
老李见和尚赢了自己的酒,但是自己还舍不得,所以就耍起了赖皮,对和尚说,光武不行,再来点文的,你给我说出来1-8的全排序,我就让你喝,这次绝不耍你,你能帮帮和尚么?
输入描述:
无
输出描述:
1~8的全排列,按照全排列的顺序输出,每行结尾无空格。
示例1
输入
No_Input
输出
Full arrangement of 1~8
备注:
1~3的全排列 :
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
注意:
遇到全排列问题可以用库函数next_permutation( )
,其意是下一个排列,与其相对的是prev_permutation( ),即上一个排序。
补充:
next_permutation( )
基本用法:next_permutation()只能获得下一个排序,如需获得全排列,即需先对数组进行升序排序
int main(){
int a[4]={2,1,4,3};
sort(a,a+4);//对数组排序
do{
for(int i=0;i<4;i++){//打印排列
cout<<a[i]<<' ';
}
cout<<endl;
}while(next_permutation(a,a+4));//获取下一个排列
}
基本定义如下:
next_permutaion(起始地址,末尾地址+1)
next_permutaion(起始地址,末尾地址+1,自定义排序)
实践代码:
void solve(){
int a[9];
for(int i=1;i<=8;i++)
{
a[i]=i;
}
do{
for(int i=1;i<=8;i++)
cout<<a[i]<<' ';
cout<<endl;
}
while(next_permutation(a+1,a+9));
}
[NOIP1998]拼数
题目:
设有n个正整数(n ≤ 20),将它们联接成一排,组成一个最大的多位整数。
例如:n=3时,3个整数13,312,343联接成的最大整数为:34331213
又如:n=4时,4个整数7,13,4,246联接成的最大整数为:7424613
输入描述:
第一行,一个正整数n。
第二行,n个正整数。
输出描述:
一个正整数,表示最大的整数
示例1
输入
3
13 312 343
输出
34331213
示例2
输入
20
921650139 925571586 931563581 923960668 870548039 358493469 371229218 737101511 514654859 185379933 19421244 117259400 301947570 48520742 79303948 222979736 153546206 250582036 106394401 198125223
输出
931563581925571586923960668921650139870548039793039487371015115146548594852074237122921835849346930194757025058203622297973619812522319421244185379933153546206117259400106394401
说明
本样例为牛客补充,非原始题目数据。此样例也添加到了本题的测试数据。
2023/1/16添加,之前的提交不进行重测。
注意:
看到第二个样例我立马就用了字符串,你要素用int,long long啥的我肯定也不拦你(试试就逝世),根据题意可知拼接(+)字符串再对拼接后的字符串进行排序。
实践代码:
bool cmp(string a,string b){
return a+b>b+a;//自定义比较器,即拼接两个字符串,判断谁在前所组成的数值的大
}
void solve(){
int n;cin>>n;
string s[n];
for(int i=0;i<n;i++){
cin>>s[i];
}
sort(s,s+n,cmp);
for(int i=0;i<n;i++) cout<<s[i];
}
心有猛虎,细嗅蔷薇。再见了朋友~