蓝桥杯模拟小赛#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;
}

浙公网安备 33010602011771号