2024.2.29|华北水利水电大学江淮校区ACM社团训练赛

这篇文章介绍了华北水利水电大学江淮校区ACM社团的训练赛题目,涉及NOIP竞赛中的多个编程挑战,包括树的计数、数字统计、记数问题、字符串排序、判断闰年、全排列以及拼数等,展示了基础的算法和编程技巧。
摘要由CSDN通过智能技术生成

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];
}

心有猛虎,细嗅蔷薇。再见了朋友~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值