【LYZS】2023暑假训练 第一周题单总结与分析

第一周题单均为入门训练,难度较低,考察程序的结构设计及数组和字符串,部分题目可使用C++中STL提高解题效率。

目录

顺序结构

P1001 A+B Problem

P3954 [NOIP2017 普及组] 成绩

P1421 小玉买文具

分支结构

P3954 [NOIP2017 普及组] 成绩

P1085 [NOIP2004 普及组] 不高兴的津津

数组

P1427 小鱼的数字游戏

P2141 [NOIP2014 普及组] 珠心算测验

字符串 

P5015 [NOIP2018 普及组] 标题统计

P1321 单词覆盖还原

P1217 [USACO1.5] 回文质数 Prime Palindromes


顺序结构

P1001 A+B Problem

P1001 A+B Problemhttps://www.luogu.com.cn/problem/P1001

算法:模拟

思路:按原题题意,读入a和b,输出a+b的结果即可。

直接解法

//输入1——C++特性,流输入输出
int main() {
    int a,b;
    cin >> a >> b;
    cout << a+b;
    return 0;
}
//输入2
int main(){
    int a,b;
	scanf("%d%d",&a,&b);
	printf("%d",a+b); 
	return 0;
}
//定义一个变量记录a+b的结果
int a,b;
int c;
int main(){
	scanf("%d%d",&a,&b);
	c=a+b;
	printf("%d",c); 
	return 0;
}

P3954 [NOIP2017 普及组] 成绩

P3954 [NOIP2017 普及组] 成绩https://www.luogu.com.cn/problem/P3954

算法:模拟

思路:按原题题意

直接解法

int a,b,c,sum;
int main(){
 //输入三个成绩 
	scanf("%d%d%d",&a,&b,&c);
	//总成绩=作业成绩×20%+×20%+小测成绩×30%+×30%+期末考试成绩×50%×50%
	sum=a*0.2+b*0.3+c*0.5;
	//输出结果 
	printf("%d",sum); 
	return 0;
}


对数据说明的分析
 关于“对于 30%的数据,A=B=0
        对于另外 30% 的数据,A=B=100
        对于 100%100% 的数据,0≤A,B,C≤100”
 
        本题数据总量不大,对于大数据量(或者数据复杂)的题目,可以根据这种数据范围的提示分类讨论 
        关于“A,B,C 都是 10 的整数倍” :也就是A,B,C乘上百分数后得到的一定是整数,不存在小数,那么最后的总成绩也就是整数。那么这里的总成绩变量可以使用int类。 


P1421 小玉买文具

P1421 小玉买文具https://www.luogu.com.cn/problem/P1421#submit

        C语言和C++都不支持小数对小数的除法。所以对于这道题,我们可以考虑将小玉持有的钱单位从“元”和“角”转换为“角”,同样的将铅笔的单价转换为19角,这样二者都变成了整数。我们进行整数除法就能求出答案。同时,“/”运算符是取商的,符合我们对结果的要求(去尾法)。

int main(){
	int a,b,c;
	cin>>a>>b;
	c=a*10+b;
	cout<<c/19;
	return 0;
}

P1075 [NOIP2012 普及组] 质因数分解

P1075 [NOIP2012 普及组] 质因数分解https://www.luogu.com.cn/problem/P1075

        由题意可知,输入的数共4个因数:1和它本身;另外两个不同质数

        为了节约计算成本,我们先求出除了1之外的较小的因数,再用除法求出较大因数。

 sqrt()是开平方函数,对应C语言库math.h,C++库为cmath。

一个数除了它本身的最大因数,小于等于这个数的开平方。

int n,a,b;
int main(){
	cin>>n;
	for(a=2;a<=sqrt(n);a++){
		if(n%a==0)
		b=n/a;
	}
	cout<<b;
	return 0;
}

分支结构

P3954 [NOIP2017 普及组] 成绩

P3954 [NOIP2017 普及组] 成绩https://www.luogu.com.cn/problem/P3954

算法:模拟

思路:按原题题意,同时使用if作条件判断

int a,b,c,sum;
int main(){
 //输入三个成绩 
	scanf("%d%d%d",&a,&b,&c);
//A=B=0
	if(a==0&&b==0)
		sum=0.5*c;
//A=B=100
	else if(a==100&&b==100)
		sum=20+30+0.5*c;
	else sum=sum=a*0.2+b*0.3+c*0.5;
	printf("%d",sum); 
	return 0;
}

循环结构

P1085 [NOIP2004 普及组] 不高兴的津津

P1085 [NOIP2004 普及组] 不高兴的津津https://www.luogu.com.cn/problem/P1085

思路:模拟

使用了for循环来记录按天输入的数据(每天的时长)

int a,b,i,v,m=0;
//一周七天,i表示周几,a表示上课时间,b表示复习班时间
	for(i=1;i<=7;i++)
	{scanf("%d%d",&a,&b);
//m记录最大值。
//将m记录为0是因为每天的时长之和一定大于0,所以将m记录为一个比它小的数字才能保证出现符合要求的数时m可以执行它的记录功能。
//两个判断没有等于号:分别对应输出格式的“靠前一天”(也就是两天程度相当时仍然保持记录的是靠前面的一天)和要求中的“超过”八小时
	if(m<(a+b)&&(a+b)>8){
//m记录时长总和,v记录星期几
	m=a+b;v=i;
	}
	}
	printf("%d",v);
	return 0;
	}

P1909 [NOIP2016 普及组] 买铅笔

P1909 [NOIP2016 普及组] 买铅笔https://www.luogu.com.cn/problem/P1909

思路:按题意,使用for输入并分类讨论,在讨论过程中使用if判断

int main(){
//ans为0与上一题相同,都是“将不可能得到的数字0赋给记录的变量,用这个变量记录正数”
    int n,ans=0,x,y,m,w;
    cin>>n;
    for(int i=1;i<=3;i++){
        cin>>x>>y;
//求n%x余数是否为0.为0则买整包可以刚好满足发礼物的要求,否则要多买一包才能够发礼物(且有剩余)
        if(n%x!=0)
		m=n/x+1; 
        else m=n/x;
//w记录得到的包数乘以每包的铅笔数量,如果w比
		w=m*y;
//判断条件1(二者满足其一就进行记录):w比ans值更小,也就是对于这款铅笔,购买可以更省钱,就更新ans为w的值
        if(w<ans||ans==0)
//条件2:如果花费记录为0(也就是连一个购买方案都没有)就先记录它
		ans=w;
    }
    cout<<ans;
    return 0;
}

数组

P1009 [NOIP1998 普及组] 阶乘之和

P1009 [NOIP1998 普及组] 阶乘之和https://www.luogu.com.cn/problem/P1009

使用高精度求阶乘的和。

using namespace std;
int n,a[90],b[90],c[90],f[90],d=0,len_a,len_b=1,len_c=1,len_ans,m=1;
int main(){
    cin>>n;
    b[0]=1; 
    for(int i=1;i<=n;i++){ 
        len_a=0; 
        int p=i;
        while(p>0){ 
            a[len_a++]=p%10;
            p/=10;
        }
        for(int j=0;j<len_a;j++) 
            for(int k=0;k<=len_b;k++)
                c[j+k]+=a[j]*b[k];
        for(int j=0;j<len_c;j++) 
            if(c[j]>9) c[j+1]+=c[j]/10,c[j]%=10;
        if(c[len_c]) len_c++; 
        len_ans=len_b,len_b=len_c,m=max(m,len_c); 
        for(int k=len_c-1;k>=0;k--) b[k]=c[k]; 
        len_c=len_a+len_ans;
        memset(c,0,sizeof(c)); 
        for(int j=0;j<m;j++){ 
            f[j]+=b[j];
            if(f[j]>9) f[j+1]+=f[j]/10,f[j]%=10; 
        }
    }
    while(!f[m]&&m>0) m--; 
    for(int i=m;i>=0;i--) cout<<f[i]; 
    return 0; 
}

P1427 小鱼的数字游戏

P1427 小鱼的数字游戏https://www.luogu.com.cn/problem/P1427

思路:用数组记录。读入一串数字,(遇到0时停止),再倒过来输出。

常规做法:使用数组

int x[100],len=0;
int main(){
    for(int i=0;;i++){
        cin>>x[i];
        if(x[i]==0) 
            break; 
        len=i;
    }
    for(int j=len;j>=0;j--)
    cout<<x[j]<<" ";
    return 0;
}

(模拟实现)栈

利用了栈先进后出的特性。

int a[105];
//top记录顶部元素在数组中的下标,c表示每次读入的数字
int top=0,c;
int main(){
	while(1){
		cin>>c;
		if(c==0) break;
		a[++top]=c;
	/*上一行代码等价于下列两行代码
            top++;
            a[top]=c;
	*/ 
		
	}
	while(top!=0){
		cout<<a[top--]<<" ";
		/*
		上一行代码等价于下列两行代码:
	    	cout<<a[top];
    		top--;
		*/ 
	}
	return 0;
} 

(C++ STL)栈

stack<int>a;
int c;
int main(){
	while(cin>>c){
		if(c==0)	break;
		a.push(c); 
	} 
	while(!a.empty()){
		cout<<a.top()<<' ';//输出顶部元素 
		a.pop() ;//弹出顶部元素 
	}
	return 0;
}

P2141 [NOIP2014 普及组] 珠心算测验P2141 [NOIP2014 普及组] 珠心算测验https://www.luogu.com.cn/problem/P2141

题意:输入一组数字,判断其中哪些数可以又数组中的另外两个数字求和得到。

注意:加数+加数=和,非负数之和一定大于两个加数。

思路:先对数组排序。在使用三层循环,结合判断。

其中sort()C++的STL库中排序函数,默认升序排序。C语言必须手写排序。

//n代表数字总数,a记录输入的数字,ans为答案,qc按下标标记数字是否可以由求和得到
int n,a[105],ans,qc[105];
int main(){
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	sort(a+1,a+n+1);
	for(int i=1;i<n-1;i++)//加数
	for(int j=i+1;j<n;j++)
	for(int k=j+1;k<=n;k++){//被加数
//加数+加数=和。如果得到的和在数组中,和对应的qc还没有标记,就标记一下为1。
//qc[k]=0的初始化可以防止重复标记
        if((a[i]+a[j]==a[k])&&qc[k]==0){
        	ans++;
        	qc[k]=1;
		}
	}
	cout<<ans;
	return 0;
}

字符串 

P5015 [NOIP2018 普及组] 标题统计

P5015 [NOIP2018 普及组] 标题统计https://www.luogu.com.cn/problem/P5015

题意:读入一个字符串,记录其中的字符数量,不记录空格和换行符。

思路:逐个读入字符串中的字符,不是空格和换行符,那么记录变量+1。

C语言没有单独的字符串类,我们用字符数组来记录字符串。可以使用gets()函数实现字符数组的读入。同时,使用strlen()函数来求字符数组(也就是字符串)的长度。

int main(){
	char s[10];
	gets(s);
	int n=strlen(s);
	int ans=0;
	for(int i=0;i<n;i++){
       //如果是大写字母
		if(s[i]>='A'&&s[i]<='Z')
		ans++;
        //如果是小写字母
		if(s[i]>='a'&&s[i]<='z')
		ans++;
        //如果是数字字符
		if(s[i]>='0'&&s[i]<='9')
		ans++;
	}
	printf("%d",ans);
	return 0;
}

C++:cin可以自动过滤掉换行符不做处理。

char s;
int ans;
int main(){
	while(cin>>s){
		if(s!=' ') 	
        	ans++;
		}
	cout<<ans;
	return 0;
}

P1321 单词覆盖还原

P1321 单词覆盖还原

C++对字符串类的处理函数使用cstring

//字符串;记录boy数量和girl数量的变量
string s;
int kb,kg;
//处理函数,在字符串s中找字符串t
int cs(string t){
	int k=0;
//求出t字符串总长度,fi记录是字符串s能否找的到t
//find(t,k)是在k下标后找串t,找到返回下标,找不到返回-1。不特意标注k则从头开始。
	int len=t.size(),fi=s.find(t);
	while(fi!=-1){//继续查找的条件是能找到
		k++;
    //找到之后用*覆盖掉串t,防止重复计算。
		s.replace(fi,len,"*");
		fi=s.find(t,fi+1);
	}
	return k;
}
//查找时,boy和girl组成的字母都不重复,分开查找就行,不用分类讨论;分别对二者查找时,先从长串(最长的串就是单词本身)寻找和覆盖,在向短的串寻找,可以防止漏数。
int main(){
	cin>>s;
	kb=cs("boy")+cs("bo")+cs("oy")+cs("b")+cs("o")+cs("y");
	       kg=cs("girl")+cs("gir")+cs("irl")+cs("gi")+cs("ir")+cs("rl")+cs("g")+cs("r")+cs("i")+cs("l");
	cout<<kb<<endl<<kg<<endl;
	return 0;
} 

P1217 [USACO1.5] 回文质数 Prime Palindromes

P1217 [USACO1.5] 回文质数 Prime Palindromeshttps://www.luogu.com.cn/problem/P1217

常规思路:先求出一亿之内所有质数,在判断是不是回文数。

解法1:埃氏筛选法+回文数判断

using namespace std;
//设置布尔型数组,数组元素记录下标数字是否为质数,是则为1 
//注意一亿是8个0,共9位 
bool book[100000001];

// 用埃氏筛法生成质数表
void isprime(int b) {
    //初始化,默认全是质数
    memset(book, true, sizeof(book));
    book[1]=false;	//1不是质数
    int n=sqrt(b);//用于判断。一个数的除了它自身的最大因数不大于它的开平方 
    for (int i=2;i<=n;i++) {
        if (book[i]) {
            //质数的倍数不是质数 
            //b/i用于限制,防止j*i>=b时浪费 
            for (int j=2;j<=b/i;j++)
                book[i*j]=false;
        }
    }
}

//判断回文数
bool is(int num) {
//temp用来求每一位
//num是原来的数字,ans用来求原数字数字顺序反过来得到的数,二者相等则num为回文数
    int temp=num,ans=0;
    while (temp!=0) {
        ans=ans*10+temp%10;
        temp/=10;
    }
    if (ans==num)
        return true;
    else
        return false;
}

int main() {
    int a,b;
    cin>>a>>b;
   /*可以证明的是,除了11以外,一个数的位数是偶数的话,不可能为回文数素数。
    如果一个回文素数的位数是偶数,则它的奇数位上的数字和与偶数位上的数字和必然相等;
    根据数的整除性理论,容易判断这样的数肯定能被11整除,所以它就不可能是素数。
    
    
    也就是说,一亿一一定不是,接下来的八位数一定都不是。所以,如果b是八位数或九位数,
为了节省时空,我们从最大七位数开始算。 
	*/
    if (b>=10000000)
        b=9999999;
    isprime(b);
    //a>b时这个输入范围不合法,不予计算 
    if(a>b)
    	return 0;
    //a是偶数那么范围再向前一下,因为a本身一定不是。 
    if (a%2==0) 
		a++;
	//除了2以外,2的倍数不可能是质数
    for (int i=a;i<=b;i+=2) {
        if (book[i] && is(i))
            cout<<i<<endl;//如果既是质数同时也是回文数,就输出。
    }
    return 0;
}

解法2:使用打表得到一个记录了1亿内质数的数组(推荐使用python),再判断。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

延7488

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值