蓝桥杯专项练习

1.回文日期

2020 年春节期间,有一个特殊的日期引起了大家的注意:2020 年 2 月 2 日。因为如果将这个日期按 “yyyymmdd” 的格式写成一个 8 位数是 20200202,恰好是一个回文数。我们称这样的日期是回文日期。

有人表示 20200202 是 “千年一遇” 的特殊日子。对此小明很不认同,因为不到 2 年之后就是下一个回文日期:20211202 即 2021 年 12 月 2 日。

也有人表示 20200202 并不仅仅是一个回文日期,还是一个 ABABBABA 型的回文日期。对此小明也不认同,因为大约 100 年后就能遇到下一个 ABABBABA 型的回文日期:21211212 即 2121 年 12 月 12 日。算不上 “千年一遇”,顶多算 “千年两遇”。

给定一个 8 位数的日期,请你计算该日期之后下一个回文日期和下一个 ABABBABA 型的回文日期各是哪一天。

自己写的代码:

#include<bits/stdc++.h>
using namespace std;
int main()
{
	string str;
	cin >> str;
	int year = (str[0] - '0') * 1000 + (str[1] - '0') * 100 + (str[2] - '0') * 10 + (str[3] - '0');
	int month = (str[4] - '0') * 10 + (str[5] - '0') * 1;
	int day = (str[6] - '0') * 10 + (str[7] - '0') * 1;
	string s, s1, s2, s3;
	bool flag = true;
	int months[12] = { 31,28,30,31,30,31,31,31,30,31,30,31 };
	while (1)
	{
		day++;
		if ((year % 400 == 0) || (year % 100 != 0 && year % 4 == 0))
			months[1] = 29;
		else
			months[1] = 28;
		if (day > months[month-1])
		{
			month++;
			day = 1;
		}
		if (month > 12)
		{
			month = 1;
			day = 1;
			year++;
		}
		s = to_string(year);
		s1="";
		if(month<10)
		s1+='0';
		s1 += to_string(month);
		if(day<10)
		s1+='0';
		s1+=to_string(day);
		reverse(s1.begin(), s1.end());
		if (s == s1)
		{
			reverse(s1.begin(), s1.end());
			if (flag)
			{
				s2 = s + s1;
				flag = false;
			}
			if (s[0]==s[2]&&s[0]==s1[1]&&s1[1]==s1[3]&&s[1]==s[3]&&s[3]==s1[0]&&s1[0]==s1[2])
			{
				s3 = s + s1;
				break;
			}
		}
	}
	cout << s2 << endl;
	cout << s3 << endl;
}

总结:1.to_string是C++11标准中的函数,在Dev c++里的代码生成中要配置一下

           2.这道题有一个必须要注意的点:把类似于03的整形转换成字符串只会有一个‘3’。所以,得判断天数和月数是否小于10。

2.数字三角形

 上图给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,你的任务就是找到最大的和。

路径上的每一步只能从一个数走到下一层和它最近的左边的那个数或者右 边的那个数。此外,向左下走的次数与向右下走的次数相差不能超过 1。

正确代码:

#include<bits/stdc++.h>
using namespace std;
int a[200][200];
int c[200][200];
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	for(int j=1;j<=i;j++)
		cin>>a[i][j];
	c[1][1]=a[1][1];
	int maxmum=0;
	for(int i=2;i<=n;i++)
	{
		for(int j=1;j<=i;j++)
		{	
			c[i][j]=a[i][j]+max(c[i-1][j-1],c[i-1][j]);
		}
	}
	cout<<max(c[n][(n+1)/2],c[n][(n+2)/2]);
}

总结:动态规划

题目中说明了向左下的次数与向右下的次数之差不能大于1,所以最后的终点一定在中间。

——————cout输出的整形有一定范围。

3.排序

小蓝最近学习了一些排序算法,其中冒泡排序让他印象深刻。

在冒泡排序中,每次只能交换相邻的两个元素。

小蓝发现,如果对一个字符串中的字符排序,只允许交换相邻的两个字符, 则在所有可能的排序方案中,冒泡排序的总交换次数是最少的。

例如,对于字符串 lan 排序,只需要 1 次交换。对于字符串 qiao 排序,总共需要 4 次交换。

小蓝找到了很多字符串试图排序,他恰巧碰到一个字符串,需要 100次交 换,可是他忘了吧这个字符串记下来,现在找不到了。

请帮助小蓝找一个只包含小写英文字母且没有字母重复出现的字符串,对 该串的字符排序,正好需要 100 次交换。如果可能找到多个,请告诉小蓝最短的那个。如果最短的仍然有多个,请告诉小蓝字典序最小的那个。

正确代码:

#include <iostream>
using namespace std;
int main()
{
//考虑冒泡排序的复杂度,对于拥有N个字母的字符串,最多需要交换N*(N-1)/2次(完全乱序时)
//易知N=15时,有15*14/2=105,即满足100次交换所需的最短字符串有15个字母。
//要求字典序最小,那么显然要取a~o这15个字典序最小的字母
/*
  逆向思考,目标字符串经过100次交换后,得到正序字符串abcdefghijklmno,而完全逆序的字符串onmlkjihgfedcba变成正序字符串需要105次交换,那么将完全逆序的字符串交换5次后,便能得到答案。
  而要求字典序最小,那么将j交换5次提到字符串最前面,就得到了最小的情况
*/
  printf("jonmlkihgfedcba");
  return 0;
}

4.跑步锻炼

小蓝每天都锻炼身体。

正常情况下,小蓝每天跑 11 千米。如果某天是周一或者月初(11 日),为了激励自己,小蓝要跑 22 千米。如果同时是周一或月初,小蓝也是跑 22 千米。

小蓝跑步已经坚持了很长时间,从 20002000 年 11 月 11 日周六(含)到 20202020 年 1010 月 11 日周四(含)。请问这段时间小蓝总共跑步多少千米?

自己写的代码:

正确代码:

#include<stdio.h>//依次判断年月日周 
int main(){
    int months[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
    int year,month,day;
    int ans=6;//一月一号是周六 
    int cnt=0;//公里数 
    for(year=2000;year<=2020;year++){
        if(year%4==0&&year%100!=0||year%400==0){
            months[2]=29;
        }else{
            months[2]=28;
        }
    for(month=1;month<=12;month++){//几月 
        for(day=1;day<=months[month];day++){//几日 
            cnt++;//每天一千米 
            if(ans==8){
                ans=1;//ans自增到 8 时归回 1 
            } 
            if(ans==1||day==1){//或意味着A对,B对,AB同时对三种情况 
                cnt++;//周一或月初或周一与月初多跑一千米 
            }
            ans++;//进入第二天 
            if(year==2020&&month==10&&day==1){//到2020.10.1结束循环 
                printf("%d",cnt);
            } 
        }
    }
}
    return 0;//一点一点来不要怕错 
}

总结:做日期类的题一定不能急,要慢慢的下手,注重细节。

5.货物摆放

小蓝有一个超大的仓库,可以摆放很多货物。

现在,小蓝有 n 箱货物要摆放在仓库,每箱货物都是规则的正方体。小蓝规定了长、宽、高三个互相垂直的方向,每箱货物的边都必须严格平行于长、宽、高。

小蓝希望所有的货物最终摆成一个大的长方体。即在长、宽、高的方向上分别堆 L、W、H 的货物,满足n=L×W×H。

给定 n,请问有多少种堆放货物的方案满足要求。

例如,当 n=4 时,有以下 6 种方案:1×1×4、1×2×2、1×4×1、2×1×2、2×2×1、4×1×1。

请问,当n=2021041820210418 (注意有 16 位数字)时,总共有多少种方案?

提示:建议使用计算机编程解决问题。

自己写的代码:

#include<bits/stdc++.h>
using namespace std;
int main()
{
	long long n=2021041820210418,sum=0;
	vector<long long>v;
	for(long long i=1;i<=sqrt(n);i++)
	{
		if(n%i==0){
		v.push_back(i);
		if(n/i!=i)
			v.push_back(n/i);
		}
	}
	for(long long x:v){
		for(long long y:v){
			for(long long z:v){
				if(x*y*z==n)
					sum++;
			}
		}
	}
	printf("%lld",sum);
}

总结:这道题关键在于求出因子组合数,先求出所有因子,再从因子中排序,就不会超时。

用数组会超时,vector不会。

6.等差素数列

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

2,3,5,7,11,13 是素数序列。 类似:7,37,67,97,127,157 这样完全由素数组成的等差数列,叫等差素数数列。

上边的数列公差为 30,长度为 6。

2004 年,格林与华人陶哲轩合作证明了:存在任意长度的素数等差数列。 这是数论领域一项惊人的成果!

有这一理论为基础,请你借助手中的计算机,满怀信心地搜索:

长度为 10 的等差素数列,其公差最小值是多少?

自己写的代码:

百度了一下,发现所有小于等差素数列的长度的素数的乘积就是该等差素数列的公差。

总结:这结论很牛啊!

7.乘积尾零

如下的 10 行数据,每行有 10 个整数,请你求出它们的乘积的末尾有多少个零?

5650 4542 3554 473 946 4114 3871 9073 90 4329 2758 7949 6113 5659 5245 7432 3051 4434 6704 3594 9937 1173 6866 3397 4759 7557 3070 2287 1453 9899 1486 5722 3135 1170 4014 5510 5120 729 2880 9019 2049 698 4582 4346 4427 646 9742 7340 1230 7683 5693 7015 6887 7381 4172 4341 2909 2027 7355 5649 6701 6645 1671 5978 2704 9926 295 3125 3878 6785 2066 4247 4800 1578 6652 4616 1113 6205 3264 2915 3966 5291 2904 1285 2193 1428 2265 8730 9436 7074 689 5510 8243 6114 337 4096 8199 7313 3685 211

正确代码:

解题思路:
题目:计算多少个零
先找出多少个能相乘等于零的
需要计算出里面有多少个数是包含五和二的
然后比较找出有多少个可以5和2可以相乘等于零
然后输出

#include <iostream>
using namespace std;
int cnt2,cnt5;
int a[100];

int main(){
  for(int i=0;i<=99;i++){
   cin>>a[i];
    while(a[i]%2==0){
      cnt2++;
      a[i]/=2;
    }
    while(a[i]%5==0){
      cnt5++;
      a[i]/=5;
    }
  }
  cout << min(cnt2,cnt5) << endl;
  return 0;
}

总结:这题刚看到的时候想多了,分了很多情况讨论......

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值