2018第九届蓝桥杯大赛软件类B组C/C++国赛题解

2018第九届蓝桥杯大赛软件类B组C/C++国赛目录

      • 试题 A:换零钞(结果填空)
      • 试题 B:激光样式(结果填空)
      • 试题 C:格雷码(结果填空)
      • 试题 D:调手表(程序设计)
      • 试题 E:搭积木(结果填空)
      • 试题 F:矩阵求和(程序设计)

试题 A:换零钞(结果填空)

题意
2018第九届蓝桥杯大赛软件类B组C/C++国赛题解_第1张图片

做法:直接模拟就可。

代码

#include
using namespace std;
int main() {
     
	int mon = 200, res = 0;
	for(int i = 1; i <= 100; ++i) {
     
		mon -= 21; res += 11;
		if(mon % 5 == 0) {
     
			res += mon / 5; break;
		}
	}
	cout << res;
	return 0;
}

答案:74


试题 B:激光样式(结果填空)

题意
2018第九届蓝桥杯大赛软件类B组C/C++国赛题解_第2张图片

做法:用的是二进制枚举判断(其实用dfs会更好),每次判断一下该情况是否合法。跑了半分钟左右。

代码

#include
using namespace std;
typedef long long LL;
int main() {
     
	int lst, x, f;
	LL res = 0;
	for(int i = 0; i < (1<<30); ++i) {
     
		lst = -1; f = 1;
		for(int j = 0; j < 30; ++j) {
     
			x = ((i>>j)&1);
			if(x == 1 && lst == 1) {
     
				f = 0; break;
			}
			lst = x;
		}
		if(f) ++res;
	}
	cout << res;
	return 0;
}

答案:2178309


试题 C:格雷码(结果填空)

题意2018第九届蓝桥杯大赛软件类B组C/C++国赛题解_第3张图片
2018第九届蓝桥杯大赛软件类B组C/C++国赛题解_第4张图片
2018第九届蓝桥杯大赛软件类B组C/C++国赛题解_第5张图片
做法:要知道a&-a可以计算到最右边的1,这个也是树状数组的核心所在,再向左挪一位再改变就可。

答案:a^((a&-a)*2)


——以下题目通过了 C语言网 的测试数据——

试题 D:调手表(程序设计)

题意2018第九届蓝桥杯大赛软件类B组C/C++国赛题解_第6张图片
2018第九届蓝桥杯大赛软件类B组C/C++国赛题解_第7张图片

做法:任意一分钟到任意一分钟可以看成是0到任意分钟,那么问题转化成以最优策略从0到达n-1以内的数中执行两种操作(+1或者+k)最多是多少。所以bfs复杂度可过。

代码

#include
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int N = 1e5+10;
int n, k, vis[N]; 
queue<pii> q;
int main() {
     
	scanf("%d %d", &n, &k);
	int s = 0, u, v, step, ans = 0;
	vis[0] = 1; q.push(make_pair(0, 0));
	while(!q.empty()) {
     
		u = q.front().fi; step = q.front().se;
		ans = max(ans, step);
		q.pop();
		v = (u + 1) % n;
		if(!vis[v]) {
     
			vis[v] = 1; q.push(make_pair(v, step+1));
		}
		v = (u + k) % n;
		if(!vis[v]) {
     
			vis[v] = 1; q.push(make_pair(v, step+1));
		}
	}
	printf("%d\n", ans);
	return 0;
}

试题 E:搭积木(结果填空)

题意2018第九届蓝桥杯大赛软件类B组C/C++国赛题解_第8张图片
2018第九届蓝桥杯大赛软件类B组C/C++国赛题解_第9张图片
2018第九届蓝桥杯大赛软件类B组C/C++国赛题解_第10张图片

做法:记忆化搜索,选择的积木是连续的,有三种情况,分别是升、先升后降、降,要搜索只限于这三种情况,所以得记录下来当前的趋势是在升还是在降。dp[i][j][k]代表第i列、上一列选了数字j、升(0)降(1)k,处理出每一列可以选的数字(low1数组),对记忆化搜索不熟悉呀,被某佬支配的恐惧(萌新瑟瑟发抖 )。

代码

#include
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int N = 210;
const LL Mod = 1e9+7;
int n, m, low1[N];
char tu[N][N];
LL dp[N][N][2]; //第i列、上一个选了数字j、升(0)降(1)k 
LL dfs(int i, int j, int k) {
     
	if(i > m) return 1;
	if(dp[i][j][k] != -1) return dp[i][j][k];
	LL ans = 0;
	for(int x = 0; x <= low1[i]; ++x) {
     
		if(!k) {
     
			if(x < j) ans += dfs(i+1, x, 1);
			else ans += dfs(i+1, x, 0);
		} else if(x <= j) ans += dfs(i+1, x, 1);
	}
	return dp[i][j][k] = ans % Mod;
}
int main() {
     
	scanf("%d %d", &n, &m);
	for(int j = 1; j <= m; ++j) low1[j] = n;
	for(int i = 1; i <= n; ++i) {
     
		scanf("%s", tu[i]+1);
		for(int j = 1; j <= m; ++j) {
     
			if(tu[i][j] == 'X') low1[j] = min(low1[j], n-i);
		}
	}
	LL ans = 0; 
	memset(dp, -1, sizeof dp);
	ans += dfs(0, 0, 0);
	printf("%lld\n", ans % Mod);
	return 0;
}

答案


试题 F:矩阵求和(程序设计)

题意
2018第九届蓝桥杯大赛软件类B组C/C++国赛题解_第11张图片

做法:貌似是莫比乌斯反演+欧拉函数?膜拜大佬

你可能感兴趣的:(2018第九届蓝桥杯大赛软件类B组C/C++国赛题解)