【蓝桥杯】枚举2

今天是【蓝桥杯】枚举2的6道真题归纳。

一、卡片

2021年A组A题,B组B题。
题目描述
本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
小蓝有很多数字卡片,每张卡片上都是数字 0 到 9。
小蓝准备用这些卡片来拼一些数,他想从 1 开始拼出正整数,每拼一个,就保存起来,卡片就不能用来拼其它数了。
小蓝想知道自己能从 1 拼到多少。
例如,当小蓝有 30 张卡片,其中 0 到 9 各 3 张,则小蓝可以拼出 1 到 10,
但是拼 1 时卡片 1 已经只有一张了,不够拼出 11。
现在小蓝手里有 0 到 9 的卡片各 2021 张,共 20210 张,请问小蓝可以从 1 拼到多少?
提示:建议使用计算机编程解决问题。

这题体现了while的优势,当不知道要枚举多大数据时,可以先写个while,找到之后跳出循环就可。要注意的是,while(n)后面如果想继续使用n的话,需要一个临时变量。

这题要注意一个点:1肯定是先用完的。
我们要找的答案是最多可以拼多少个。
即n一定包含1,答案是n-1。

方法一:我的代码

#include<iostream>
using namespace std;

int nums[10];

int main(void)
{
	for(int i = 0; i <= 9; i++)
		nums[i] = 2021;
	
	int n = 1;
	while(1)
	{
		int res = n;
		for(int i = 0; res; i++)
		{
			nums[res % 10]--;
			res /= 10;
		}
		
		for(int i = 0; i <= 9; i++)
			if(nums[i] < 0)
			{
				cout<< n-1 << endl;
				return 0;
			}
		n++;
	}
	return 0;
} 

方法二:带练学长的代码

#include<iostream>
using namespace std;

int main(void)
{
	int cnt[10];
	for(int i = 0; i <= 9; i++)
		cnt[i] = 2021;
	
	int n = 1;
	while(true)
	{
		int res = n;
		while(res)
		{
			cnt[res % 10]--;
			if(cnt[res % 10] < 0)
			{
				cout<< n-1 << endl;
				return 0;
			}
			res /= 10;
		}
		n++;
	}
	return 0;
}

方法三:老师的代码

#include<iostream>
using namespace std;

int main(void)
{
	int cnt[10];
	for(int i = 0; i <= 9; i++)
		cnt[i] = 2021;
	
	int n = 1;
	while(true)
	{
		int res = n;
		while(res)
		{
			int now = res % 10;
			if(cnt[now] > 0) 
				cnt[now]--;
			else 
				break;
			res /= 10;
		}
		if(res)   //while(res)没执行完。
			break;  //用于跳出双重循环。
		n++;
	}
	cout<< n-1 << endl;
	return 0;
}

二、直线

2021年B组C题。
考察:直线的表示,去重统计。
点的结构体表示,map。

#include<bits/stdc++.h>
using namespace std;

struct Point{
	double x,y;
}p[23*23];

map<pair<double,double>,int> line;

int main(void)
{
	int k = 0;
	for(int i = 0; i < 21; i++)  
		for(int j = 0; j < 20; j++)
		{
			p[k].x = i;
			p[k].y = j;
			k++;
		}	
		
	int cnt = 20 + 21;
	for(int i = 0; i < k; i++)
		for(int j = 0; j < k; j++)
		{
			if(p[i].x == p[j].x || p[i].y == p[j].y)
				continue;
			double k = (p[j].y - p[i].y) / (p[j].x - p[i].x);
			double b = (p[j].x*p[i].y - p[j].y*p[i].x) / (p[j].x - p[i].x);//p[i].y - k*p[i].x;
			if(line[{k,b}] == 0)
			{
				line[{k,b}] = 1;
				cnt++;
			}  
		}
	cout<< cnt << endl;  //40257
	return 0;
}

小补课:unordered_set, unordered_map每次的插入,删除复杂度是O(1)
set,map每次插入,删除是O(longn)。
multiset, multimap头文件是set。可以有重复元素。

#include<iostream>
#include<cstring>
#include<algorithm>
//#include<unordered_set>  
#include<set>
using namespace std;

int main(void)
{
	int n;
	cin>> n;
	//unordered_set<string> hash;  
	set<string> hash;
	while(n--)
	{
		string str;
		cin>> str;
		hash.insert(str);
	}
	cout<< endl;
	cout<< hash.size() << endl;
	for(auto s:hash)
		cout<< s << endl;
	
return 0;
}

c语言实现栈,队列——数组模拟栈,队列。
c++实现栈,队列——如下。

#include<stack>
#include<queue>
stack<int> stack;
queue<int> q;
queue<string> s;  //emmm应该是这样

三、回文日期

2020A组F题。

这题,思路好想。是代码量的问题。
写三个函数:回文检验函数,ABABBABA检验函数,有效日期函数。

#include<iostream>
using namespace std;

int num1[105],num2[105],num3[105];
int day[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};

bool check_a(int n)
{
	int i = 1;
	while(n)
	{
		num1[i] = n % 10;
		n /= 10;
		i++;
	}
	if(num1[1]==num1[8] && num1[2]==num1[7] && num1[3]==num1[6] && num1[4]==num1[5])
		return true;
	return false;
}

bool check_b(int n)
{
	int j = 1;
	while(n)
	{
		num2[j] = n % 10;
		n /= 10;
		j++;
	}
	if(num2[1]==num2[8] && num2[2]==num2[7] && num2[3]==num2[6] && num2[4]==num2[5])
		if(num2[1]==num2[3] && num2[2]== num2[4] && num2[1]!=num2[2])
			return true;
	return false;
}

//闰年判断函数
bool is_leap(int year)
{
	if(year%4 == 0 && year%100 != 0 || year%400 == 0)	
		return true;
	return false;
} 
int dayofmonth(int year,int month)
{
	if(month == 2)
		return is_leap(year)+28;
	return day[month];
}
//判断日期是否合法
bool check_c(int n)
{
	int year = n / 1000;
	
	int k = 1;
	while(n)
	{
		num3[k] = n % 10;
		n /= 10;
		k++;
	}
	int month = num3[4]*10+num3[3];
	if(month > 12)
		return false;
	
	int day = num3[2]*10 + num3[1];
	if(day <= dayofmonth(year,month))
		return true;
	return false;
}

int main(void)
{
	int n;
	cin>> n;
	
	int flag = 0;
	while(1)
	{
		n++;
		if( !check_c(n) )
			continue;
		
		if( check_a(n) && flag == 0 )
		{
			cout<< n << endl;
			flag = 1;
		}	
		if( check_b(n) )
		{
			cout<< n;
			return 0;
		}
	}
	return 0;
}

四、合法日期

题目描述
小蓝正在上小学,老师要求同学们在暑假每天记日记。可是小蓝整个暑假都在玩,直到最后一天才想起要记日记。于是小蓝赶紧编了一些日记交给老师。
没想到,日记很快就被老师发现了问题,原来小蓝记完 8 月 31 日的日记,竟又记了 8 月 32 日和 8 月 33 日的日记。这显然是有问题的,因为根本没有 8 月 32 日和 8 月 33 日。
给定一个月份和一个日期,请问 2021 年有没有这一天。
输入描述
输入的第一行包含一个整数 m,表示月份。
第二行包含一个整数 d,表示日期。
其中,1≤m≤20,1≤d≤40。
输出描述
如果2021年有 m 月 d 日,输入 yes,否则输出 no。

题目明确说明是2021年。2021是平年,即2月有28天。

#include<iostream>
using namespace std;

int day[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};

int main(void)
{
	int m,d;
	cin>> m >> d;
	
	if(d <= day[m])
		puts("yes");
	else 
		puts("no");
	return 0;
} 

五、特别数的和

题目描述
小明对数位中含有 2、0、1、9 的数字很感兴趣(不包括前导 0),在 1 到 40 中这样的数包括 1、2、9、10 至 32、39 和 40,共 28 个,他们的和是 574。
请问,在 1 到 n 中,所有这样的数的和是多少?

输入格式:
输入一行包含一个整数 n(1≤n≤104 )。
输出描述
输出一行,包含一个整数,表示满足条件的数的和。

写一个check()函数

#include<iostream>
using namespace std;

bool check(int x)
{
	while(x)
	{
		if(x % 10 <= 2 || x % 10 == 9)
			return true;
		x /= 10;
	}
	return false;
}

int main(void)
{
	int n;
	cin>> n;
	
	int sum = 0;
	for(int i = 1; i <= n; i++)
		if(check(i))
			sum += i;
	cout<< sum << endl;
	return 0;
} 

六、猴子分香蕉

题目描述
本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
5 只猴子是好朋友,在海边的椰子树上睡着了。这期间,有商船把一大堆香蕉忘记在沙滩上离去。
第 1 只猴子醒来,把香蕉均分成 5 堆,还剩下 1 个,就吃掉并把自己的一份藏起来继续睡觉。
第 2 只猴子醒来,把香蕉均分成 5 堆,还剩下 2 个,就吃掉并把自己的一份藏起来继续睡觉。
第 3 只猴子醒来,把香蕉均分成 5 堆,还剩下 3 个,就吃掉并把自己的一份藏起来继续睡觉。
第 4 只猴子醒来,把香蕉均分成 5 堆,还剩下 4 个,就吃掉并把自己的一份藏起来继续睡觉。
第 5 猴子醒来,重新把香蕉均分成 5 堆,哈哈,正好不剩!
请计算一开始最少有多少个香蕉。

#include<iostream>
using namespace std;

bool check(int x)
{
	int i;
	for(i = 1; i <= 4; i++)
	{
		if(x == 0 || x % 5 != i)
			return false ;
		x -= i;
		x = x*4/5;
	}
	
	if(i == 5)
	{
		if(x == 0 || x % 5 != 0)
			return false;
	}
	return true;
}

int main(void)
{
	int n = 1;
	while(1)
	{
		if(check(n))
		{
			cout<< n;  //3141
			return 0;
		}
		n++;
	}
	return 0;
} 

持续更新,欢迎一起学习!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

qing小星星

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

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

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

打赏作者

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

抵扣说明:

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

余额充值