【蓝桥杯预备营集结十】软件类 C/C++ 预备试题分析及解答

🎉🎉 目前持续总结更新,请持续关注!!! 🎉🎉

💗 大家好🤗🤗🤗,我是左手の明天!💗

📆 最近更新:2022 年 4 月 18 日,左手の明天的第 229 篇原创博客

🥇 更新于专栏:蓝桥杯预备营

🌟🌟 往期必看 🌟🌟

【蓝桥杯预备营集结一】软件类 C/C++ 预备试题分析及解答

【蓝桥杯预备营集结二】软件类 C/C++ 预备试题分析及解答

【蓝桥杯预备营集结三】软件类 C/C++ 预备试题分析及解答

【蓝桥杯预备营集结四】软件类 C/C++ 预备试题分析及解答

【蓝桥杯预备营集结五】第十三届蓝桥杯模拟赛 C/C++ 试题分析及解答

【蓝桥杯预备营集结六】软件类 C/C++ 预备试题分析及解答

【蓝桥杯预备营集结七】软件类 C/C++ 预备试题(分支结构+循环结构类)分析及解答

【蓝桥杯预备营集结八】软件类 C/C++ 预备试题分析及解答

【蓝桥杯预备营集结九】软件类 C/C++ 预备试题分析及解答


目录

🚩亲密数

🚩世纪末的星期

🚩啤酒和饮料

🚩高斯日记

🚩排它平方数

🚩换硬币

🚩翻硬币

🚩三部排序


👍👍👍👍👍👍

🌟🌟 预祝各位在每一届中能够得到好的名次 🌟🌟

🚩亲密数

⭐️问题描述

假设有 a、b 两个数,若 a 的所有因子之和等于 b,b 的所有因子之和等于 a,并且 a 不等于 b,则称 a 和 b 是一对亲密数。如 284 和 220 就是一对亲密数。

⭐️代码

#include<stdio.h>
int main()
{
    int a,b,i,n;
    for(a=1;a<=10000;a++)
    {
        for(b=0,i=1;i<=a/2;i++)
            if(a%i==0)
                b+=i;
        for(n=0,i=1;i<=b/2;i++)
            if(b%i==0)
                n+=i;
        if(n==a&&a!=b&&a<b)
            printf("%d-%d\n",a,b);
    }
    return 0;
}
#include <stdio.h>
#include <stdlib.h>
int g[100000];
int main()
{
    int a, b, m, n, k;
    scanf("%d %d", &a, &b);
    for (m = a; m <= b; m++)
    {
        for (n = 2, k = 1; n <= m / 2; n++) 
        {
            if (m % n == 0)
            {
                k = k + n;
            }
        }
        g[m] = k;
    }
    for (m = a; m < b;m++)
    {
        for (n = m + 1; n <= b; n++)
        {
            if (g[m] == n && g[n] == m)
            {
                printf("%d %d\n", m, n);
            }
        }
    }
    return 0;
}

🚩世纪末的星期

⭐️问题描述

曾有邪教称 1999 年 12 月 31 日是世界末日。当然该谣言已经不攻自破。还有人称今后的某个世纪末的 12 月 31 日䊵如果是星期一则会....

有趣的是 任何一个世纪末的年份的 12 月 31 日都不可能是星期一!!

于是 “谣言制造商”又修改为星期日......

1999 年的 12 月 31 日是星期五,请问,未来哪一个离我们最近的一个世纪末年即 xx99年的 12 月 31 日正好是星期天,即星期日

请回答该年份,只写这个 4 位整数,不要写 12 月 31 等多余信息

⭐️思路

主要还是判断闰平年,已知1999年12月31日是星期五,初始化day=5;因为是qiu最后一天是 星期几,所以直接判断闰平年,加上这一年的天数,然后判断是否可以整除7 即可,最后添加附加条件,世纪末年为xx99,所以year%100为99即可。

⭐️代码

#include<stdio.h>
int main ()
{

    int day=5;
    int year=2000;
    do{
        if(year%4==0&&year%100!=0||year%400==0)
            day=day%7+366;
        else
            day=day%7+365;

        if(day%7==0&&year%100==99)
        {
            printf("%d",year);
            break;
        }
        year++;  
    }while(year<=9999);
    return 0;
}

⭐️结果

答案:2299


🚩啤酒和饮料

⭐️问题描述

啤酒每罐 2.3 元,饮料每罐 1.9 元。小明买了若干啤酒和饮料,一共花了 82.3 元。我们还知道他买的啤酒比饮料的数量少,请你计算他买了几罐啤酒。

⭐️思路分析

分析:题目本身循环就行

主要在于如何判断两个浮点类型的数据相等

fabs():取绝对值函数 存放在math.h里

判断|a-b|<=0.0000000000001即可

⭐️代码

#include<iostream>
using namespace std;
#include<math.h>
 
int main()
{
    double pi,yi;
    for(pi=0;pi<=50;pi++)
    {
        for(yi=pi+1;yi<=50;yi++)
        {
            if(fabs(2.3*pi+1.9*yi-82.3)<=1e-8)
                cout<<pi<<endl;
        }
    }
    return 0;
}

⭐️结果

答案:11


🚩高斯日记

⭐️问题描述

大数学家高斯有个好习惯:无论如何都要记日记。他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210

后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。这或许也是个好
习惯,它时时刻刻提醒着主人:日子又过去一天,还有多少时光可以用于浪费呢?

高斯出生于:1777 年 4 月 30 日。

在高斯发现的一个重要定理的日记上标注着:5343,因此可算出那天是:1791 年 12 月 15
日。

高斯获得博士学位的那天日记上标着:8113 请你算出高斯获得博士学位的年月日。

提交答案的格式是:yyyy-mm-ddy,例如:1980-03-21

⭐️解题思路

1、我们计算出高斯出生的那一天到出生年末的时间t1,我们用总的天数t减去t1,这样方便我们计算年数;

2、我们对接下来的每年相加,直到得到第一个天数大于t的年份,则该年份就是我们要求出的年份,按照同样的方法求出月份;

3、天数就是t减去以上的时间剩下的结果,还要注意特定的输出格式,输出结果中当天数和月份为个位数的时候,不是直接输出一个数,而是前面带有0,因此应对输出进行控制。

⭐️代码

#include<iostream>  
#include<iomanip>  
using namespace std;  
int a[2][12]={{31,28,31,30,31,30,31,31,30,31,30,31},{31,29,31,30,31,30,31,31,30,31,30,31}};   //存储闰年和非闰年的各月份天数
int b[2]={365,366};      //存储闰年和非闰年的各年份的天数
int judge(int year)     //判断平年闰年的函数   
{  
    if(year%400==0||year%4==0&&year%100!=0)
    return 1;    //是闰年
    else 
    return 0;    //非闰年
}  
void show(int year,int month,int day)      //输出格式控制函数   
{  
    cout<<year<<"-";  
    cout<<setw(2)<<setfill('0')<<month<<"-";   //对于一位数的月份前面补0
    cout<<setw(2)<<setfill('0')<<day<<endl;    //对于一位数的天数前面补0
}  
int main()  
{  
    int year=1777;  
    int month=4;  
    int day=30;  
    int total=8113;  
    int num=1;  
    while(++month<=12)
    num += a[0][month-1];             //将1777年的剩余天数减去(即先存储在num中) 
    month=0;day=0;                   //月份和天数清零   
    while((num+=b[judge(++year)])<=total);   
    num -= b[judge(year)];          //找到了对应的年份   
    while((num+=a[judge(year)][++month])<=total);  
    num -= a[judge(year)][month];   //找到了对应的月份   
    day = total - num;             //找到对应的天数
    show(year,month,day);           //将结果输出   
}   

⭐️结果

答案:  "1799-07-16"


🚩排它平方数

⭐️问题描述

小明正看着 203879 这个数字发呆。 原来,203879 * 203879 = 41566646641 这有什么神奇呢?仔细观察,203879 是个 6 位数,并且它的每个数位上的数字都是不同的,并且它平方后的所有数位上都不出现组成它自身的数字。具有这样特点的 6 位数还有一个,请你找出它!

再归纳一下筛选要求:

1. 6 位正整数

2. 每个数位上的数字不同

3. 其平方数的每个数位不含原数字的任何组成数位

答案是一个 6 位的正整数。

⭐️代码

#include <iostream>
using namespace std;
int main()
{
    int ii[6];
    for (long long int i = 123456; i < 987654; i++)
    {
        int a = 1;//标记第2个要求是否通过
        int b = 1;//标记第3个要求是否通过
        int k = 0;
      long long  int h = i;
        while (h)//记录每一位数字
        {
            ii[k++] = h % 10;
            h /= 10;
        }
       long long  int hi = i;
        int t = 0;//记录位数
        while (hi)//判断是否每一位都不同
        {
            int hh = hi % 10;
            for (int j = 0; j < 6; j++)
            {
                if (t != j && hh == ii[j])
                {
                    a = 0;
                    break;
                }
            }
            if (a == 0) break;
            hi /= 10;
            t++;
        }
        if (a == 0)continue;
        long long int s = i * i; 
        while (s)//判断是否平方和不重复原来的数
        {
            int ss = s % 10;
            for (int jj = 0; jj < 6; jj++)
            {
                if (ss == ii[jj])
                {                 
                    b = 0;
                    break;
                }
            }
            if (b == 0)
                break;
            s /= 10;
        }
        if (b == 0)
           continue;
        cout << i << endl;
    }
}

⭐️结果

答案:639172


🚩换硬币

⭐️问题描述

想兑换100元零钱,有1元、2元、5元、10元四种面值,总有多少种兑换方法?

⭐️解题思路

本题可以采用多种方法求解。最容易理解的应该就是暴力穷举递归求解

⭐️方法一:暴力穷举

100元换成1元,2元,5元,10元四种面值,那么考虑四种临界情况:
如果全部换成1元硬币, 则可换100个。
如果全部换成2元硬币, 则可换50个。
如果全部换成5元硬币, 则可换20 个。
如果全部换成10元硬币,则可换10个。
所以穷举范围就很清楚了,如果定义变量a,b,c,d分别表示1元,2元,3元,4元硬币的个数。那么:

0<=a<=100;               
0<=b<=50  ;              
0<=c<=20  ;               
0<=d<=10  ;                  
#include <stdio.h>
int main() 
{
	int g_count=0;
	int a,b,c,d;
	for(a=0; a<=100; a++)
	{
		for(b=0; b<=50; b++)
		{
			for(c=0; c<=20; c++)
			{
				for(d=0; d<=10; d++)
				{
					if(100==a+2*b+5*c+10*d)
					{
						g_count++;	
					}
				}
			}
		}
	}
	printf("%d\n",g_count);
	return 0;
}

⭐️方法二:递归求解

#include <iostream>
using namespace std; 

const int N = 100;  
int dimes[] = {1, 2, 5, 10};  
int arr[N+1] = {1};  

int coinExchange(int n, int m) //递归方式实现,更好理解
{  
  if (n == 0)   //跳出递归的条件
        return 1;  
  if (n < 0 || m == 0)  
        return 0; 
 return (coinExchange(n, m-1) + coinExchange(n-dimes[m-1], m));  
  //分为两种情况:换取当前面值的情况 + 没有换取当前面值的情况
  //如果没有换当前硬币,那么是多少?加上,如果换了当前硬币,总值减少,此时又是多少种兑换方法?
}
int main()
{
  int num=coinExchange(N, 4); 
  cout<<num<<endl; 
  return 0; 
}

🚩翻硬币

⭐️问题描述

小明正在玩一个“翻硬币”的游戏。

桌上放着排成一排的若干硬币。我们用 * 表示正面,用 o 表示反面(是小写字母,不是零)。

比如,可能情形是:oo*oooo

如果同时翻转左边的两个硬币,则变为:oooo***oooo

现在小明的问题是:如果已知了初始状态和要达到的目标状态,每次只能同时翻转相邻的两个硬币,那么对特定的局面,最少要翻动多少次呢?

我们约定:把翻动相邻的两个硬币叫做一步操作,那么要求:

输入格式
两行等长的字符串,分别表示初始状态和要达到的目标状态。每行的长度<1000

输出格式
一个整数,表示最小操作步数。

输入样例1:

**********
o****o****

输出样例1:

5

输入样例2:

*o**o***o***
*o***o**o***

输出样例2:

1

⭐️思路分析

我们找开始的字符串和目标字符串的相邻的两个不同,进行相减,就能得到从上面到下面的字符串需要进行多少步,然后再继续找下一个两个不同,以此类推就可以得到答案了!!

#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
using namespace std;
bool res=false;
int index1;
int sum = 0;
int main() {
	string start;
	string target;
	cin >> start >> target;
	int len = start.size();
	
	for (int i = 0; i < len; i++) {
		if (start[i] != target[i]) {
			if (res == false) {
				index1 = i;
				res = true;
			}
			else {
				sum += i - index1;
				res = false;
			}
		}
	}
	cout << sum << endl;
	return 0;
}

🚩三部排序

⭐️问题描述

一般的排序有许多经典算法,如快速排序、希尔排序等。 但实际应用时,经常会或多或少有一些特殊的要求。我们没必要套用那些经典算法,可以根据实际情况建立好的解法。

比如,对一个整型数组中的数字进行分类排序,使得负数都靠左端,正数都靠右端,0 在中部。

注意问题的特点是:负数区域和正数区域内并不要求有序。可以利用这个特点通过 1 次线性扫描就结束战斗!!

⭐️代码

#include<stdio.h>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
void sort3p(int* x, int len)
{
	int p = 0;
	int left = 0;
	int right = len-1;
	
	while(p<=right){	
		if(x[p]<0){			//小于零的数往左边移 
			int t = x[left];
			x[left] = x[p];
			x[p] = t;
			left++;
			p++;
		}
		else if(x[p]>0){		//大于零的数往最右边移 
			int t = x[right];
			x[right] = x[p];
			x[p] = t;
			right--;			
		}
		else{	//x[p]==0
			p++;  
		}
		for(int i=0;i<14;i++)
       			 printf("%d,",x[i]);  
    	puts("\n");   	
	}
	
}
 
int main()  
{  
	int a[14]={25,18,-2,0,16,-5,33,21,0,19,-16,25,-3,0};
	sort3p(a,14);
	for(int i=0;i<14;i++)
        printf("%d,",a[i]);  
    return 0;  
}

其中 x 指向待排序的整型数组,len 是数组的长度。


🍊🍊🍊

总结不易,看到这那就来个三连吧,肝。。。🍺🍺🍺

🍊🍊🍊

署名:左手の明天

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

左手の明天

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

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

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

打赏作者

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

抵扣说明:

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

余额充值