2019 蓝桥杯省赛 B 组模拟赛(三) 填空题

题目1:结果填空:18岁生日
在这里插入图片描述
代码如下:

#include<bits/stdc++.h>
using namespace std;
bool leap(int year)
{
	if(year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) return true;
	return false;
}
int main()
{
	int sum = 0;
	for(int i = 0;i < 18;i++){
		if(leap(i + 2015)) sum += 366;
		else sum += 365;
	}
	cout << sum << endl;
	return 0;	
} 
最终答案:6575

这道题非常简单,只要判断从2015年一直到2032年期间每一年是平年还是闰年就可以了,平年天数加365,闰年天数加366。

题目2:结果填空:数字拆分
在这里插入图片描述
代码如下:

#include<bits/stdc++.h>
using namespace std;
int dp[100];
int main()
{
	int n;
	cin >> n;
	dp[0] = 1;
	for(int i = 1;i <= n;i++){
		for(int j = i;j <= n;j++){
			dp[j] += dp[j - i];
		}
	} 
	cout << dp[n] << endl;
	return 0;
}
最终答案:42

这道题和背包问题种的完全背包问题很类似,假设要分解的数为n,那么就相当于从1,2,3…n这些数中任取,取出来所有的数之和为n就可以了,这里的1,2…n这些数取的次数是没有限制的。上述代码写的是经过空间压缩得出的。

题目3:结果填空:一笔画
在这里插入图片描述
在这里插入图片描述
代码如下:

#include<bits/stdc++.h>
using namespace std;
int ans = 0,dir[4][2] = {{1,0},{0,1},{-1,0},{0,-1}};
bool vis[3][5];
void dfs(int x,int y,int step)
{
	cout << x << " " << y << " " << step << endl;
	if(x == 2 && y == 0){
		if(step == 15) ans++;
		return;
	}
	for(int i = 0;i < 4;i++){
		int tx = x + dir[i][0];
		int ty = y + dir[i][1];
		if((!vis[tx][ty]) && tx >= 0 && tx < 3 && ty >= 0 && ty < 5){
			
			vis[x][y] = true;
			dfs(tx,ty,step + 1);
			vis[x][y] = false;
		}
	}
	
}
int main()
{
	vis[0][0] = true;
	dfs(0,0,1);
	cout << ans << endl;
	return 0;
}
最终答案为:4

这道题我是用dfs去完成的,将初始的位置和步数传入函数,刚开始从1步算起。每次走到位置(2,0),且步数达到15,可能数就累加一次,因为代表这是一种能达到终点的可能,且路过所有格子。最终次数就是能走到出口且路过所有格子的方案数。

题目4:结果填空:排列
在这里插入图片描述
在这里插入图片描述
代码如下:

#include<bits/stdc++.h>
using namespace std;
const int MAX = 1e9 + 7;
long long dp[20][1 << 20];//表示第i行状态为j的所有可能 
int state[1 << 20],sum = 0; 
int main()
{
	long long n,k = 0;
	cin >> n;
	dp[0][0] = 1;
	for(int i = 0;i < (1 << n);i++){
		if(!(i & (i >> 1))) state[k++] = i;//选出所有的可能保存下来,确保每次选的右边都没人 
	} 
	for(int i = 1;i <= n;i++){
		for(int j = 0;j < k;j++){
			for(int a = 0; a < k;a++){
				if(!(state[j] & state[a])){	//保存下边没人坐 
					dp[i][j] += dp[i - 1][a];//第i行状态为j的所有可能等于第i - 1行所有的状态数之和 
					dp[i][j] %= MAX; 
				}
			}
			if(i == n) sum += dp[i][j],sum %= MAX;
		}
	} 
	cout << sum << endl;
	return 0;	
} 

这道题是一道典型的状压dp,看了好久题解才明白。首先保存出所有一排位置坐人的可能状态,i & (i >> 1)作用是排除左右坐人的可能,然后一排一排开始累计所有的可能,到最后一排的时候把所有的可能加起来就是总和。
不懂状压dp的人可以看https://blog.csdn.net/u011077606/article/details/43487421,个人感觉写的很好。
题目5:代码填空:排序
在这里插入图片描述
代码如下:

#include <bits/stdc++.h>
using namespace std;
const int N = 110;
int a[N];
int main() {
	int n;
	cin >> n;
	for (int i = 0; i < n; i++) {
		int x;
		cin >> x;
		a[x]++;
	}
	for (int i = 100; i >= 0; i--) {
		for(int j = a[i];j > 0;j--) {
			cout << i << endl;
		}
	}
	return 0;
}
答案:for(int j = a[i];j > 0;j--) 

这就是一道桶排序问题,非常简单,注意检验答案的时候可以输入几个重复的成绩来验证一下。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值