蓝桥杯模拟小赛#1 题解

蓝桥杯模拟小赛#1 题解

A

枚举 \(1 - 2020\) 之间所有整数判断即可,用一个计数器记录答案个数。

#include<bits/stdc++.h>
using namespace std;
int main(){
	int ans = 0;
	for(int i = 1; i <= 2020; i ++){
		if(2020 % i == 0 && 3030 % i == 0) ans ++;
	}
	cout << ans;
	return 0;
} 

B

本题比较考验精度控制

分母肯定不会很大,于是分别枚举 \(a\)\(b\) 的分母 \(1 - 200000\) 因为可能会有重复,所以令 \(a < b\) 然后用浮点数精度判等法就可以了。

#include<bits/stdc++.h>
using namespace std;
const double eps = 1e-14;
int main(){
	int ans = 0;
	double pd = 2.0 / 45.0;
	for(int i = 1; i <= 20000; i ++){
		for(int j = i + 1; j <= 20000; j ++){
			double a = i;
			double b = j;
			if(fabs(1.0 / a + 1.0 / b - pd) < eps){
//				cout << i << " " << j << endl;
				ans ++;
			}
		}
	}
	cout << ans << endl;
	return 0;
} 

C

考验蓝桥杯神器:next_permutation

无论是写暴力还是排列数问题,这个函数都很好用,一定要会用。

#include<bits/stdc++.h>
using namespace std;
int main(){
	int cnt = 0;
	string s, p;
	cin >> s;
	p = s;
	sort(s.begin(), s.end());
	do{
		if(s == p) break;
		cnt ++;
	}while(next_permutation(s.begin(), s.end()));
	cout << cnt << endl;
	return 0; 
}

D

最小生成树板子题。

如果第一次做这种类型的题应该也有一点思路,借助并查集还有结构体排序就能实现。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 1e5 + 5;
ll n, m, fa[N], ans;
struct node{
	ll x, y, z;
}a[N];
bool cmp(node xx, node yy){
	return xx.z < yy.z;
}
void init_set(){
	for(int i = 1; i < N; i ++){
		fa[i] = i;
	}
}
ll find_set(ll x){
	return fa[x] = fa[x] == x ? fa[x] : find_set(fa[x]);
}
void union_set(ll x, ll y){
	x = find_set(x);
	y = find_set(y);
	fa[x] = fa[y];
}
int main(){
	cin >> n >> m;
	for(int i = 1; i <= m; i ++){
		cin >> a[i].x >> a[i].y >> a[i].z;
		ans += a[i].z;
	}
	sort(a + 1, a + m + 1, cmp);
	init_set();
	for(int i = 1; i <= m; i ++){
		if(find_set(a[i].x) == find_set(a[i].y)) continue;
		union_set(a[i].x, a[i].y);
		ans -= a[i].z;
	}
	cout << ans << endl;
	return 0;
}

E

考察搜索(BFS)。

最开始想这道题以为是一道数学题,后面发现不是,就第一步转化思路有点像。

用映射的思想,取任意两个数 \(x < n\)\(y < n\) 那么 \(x → y\) 等价于 \((x-x) → (y -x)\)

其实就是 \(0 → (y - x)\) 也就是求 \(0 → z\) 的最大步数(\(z < n\)),考虑 BFS剪枝 即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MAXN = 1e5 + 5;
ll n, k, flag[MAXN], ans;
struct node{
	ll idx, cnt;
};
int main(){
	ios::sync_with_stdio(false);
	cin >> n >> k;
	queue<node> op;
	op.push({0, 0});
	flag[0] = 1;
	while(!op.empty()){
		node qwq = op.front();
		op.pop();
		ans = max(ans, qwq.cnt);
		if(!flag[(qwq.idx + 1) % n]){
			flag[(qwq.idx + 1) % n] = 1;
			op.push({(qwq.idx + 1) % n, qwq.cnt + 1});
		}
		if(!flag[(qwq.idx + k) % n]){
			flag[(qwq.idx + k) % n] = 1;
			op.push({(qwq.idx + k) % n, qwq.cnt + 1});
		}
	}
	cout << ans << endl;
	return 0;
}

F

考察 二分BFS

二分最大高度差 然后 BFS 判断是否能从一个路标点出发达到所有路标点即可。

为什么只要一个路标点能够到达所有路标点,那么所有路标点都可以两两互达,画个图看一下就知道了,最后画出来是一个无向图,如果起点是 s 对于一条路径 \((x, y)\) 一定存在 (\(x, s\)) + (\(s, y\))。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MAXN = 505;
ll n, m, a[MAXN][MAXN], cnt, sx, sy;
bool vis[MAXN][MAXN], flag[MAXN][MAXN];
ll dx[4] = {0, -1, 1, 0};
ll dy[4] = {1, 0, 0, -1};
struct point{
	ll x, y;
};
bool check(ll x){
	queue<point> op;
	op.push({sx, sy});
	memset(flag, 0, sizeof flag);
	flag[sx][sy] = 1;
	ll tot = 1;
	while(!op.empty()){
		point qwq = op.front();
		op.pop();
		for(int i = 0; i < 4; i ++){
			ll xx = qwq.x + dx[i];
			ll yy = qwq.y + dy[i];
			if(xx < 1 || yy < 1 || xx > n || yy > m) continue;
			if(abs(a[xx][yy] - a[qwq.x][qwq.y]) > x) continue;
			if(flag[xx][yy]) continue;
			flag[xx][yy] = 1;
			if(vis[xx][yy]) tot ++;
			op.push({xx, yy});
		}
	}
	return tot == cnt;
}
int main(){
	ios::sync_with_stdio(false);
	cin >> n >> m;
	for(int i = 1; i <= n; i ++){
		for(int j = 1; j <= m; j ++){
			cin >> a[i][j];
		}
	}
	for(int i = 1; i <= n; i ++){
		for(int j = 1; j <= m; j ++){
			cin >> vis[i][j];
			if(vis[i][j] == 1){
				cnt ++;
				sx = i;
				sy = j;
			}
		}
	}
	ll l = -1, r = 1e9 + 5;
	while(l + 1 < r){
		ll mid = l + r >> 1;
		if(check(mid)) r = mid;
		else l = mid;
	}
	cout << r << endl;
	return 0;
} 
posted @ 2024-03-27 20:43  XiaoMo247  阅读(98)  评论(0)    收藏  举报