【2022年第十三届蓝桥杯C/C++ B组国赛】个人题解

目录

A.2022

解题思路:

参考代码:

B.钟表

解题思路:

参考代码:

C.卡牌

解题思路:

参考代码:

D.最大数字

解题思路:

参考代码:

E.出差

解题思路:

参考代码:

F.费用报销

解题思路:

参考代码:

G.故障

解题思路:

参考代码:

H.机房

解题思路:

参考代码:

I. 齿轮

解题思路:

参考代码:

J.搬砖

解题思路:

参考代码:


A.2022(379187662194355221)

解题思路:

经典01背包,直接套模板

参考代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e5 + 5;
int n = 2022;
ll f[15][3000];
int main() {
	f[0][0] = 1;
	for (int i = 1; i <= n; i++) {
		for (int j = 10; j >= 1; j--) {
			for (int k = i; k <= n; k++) {
				f[j][k] += f[j - 1][k - i];
			}
		}
	}
	cout << f[10][n];
	return 0;
}

B.钟表

解题思路:

枚举即可,再判断是否符合题目条件

参考代码:

#include<bits/stdc++.h>
using namespace std;
#define double long double
const int N = 1e5 + 5;
int s, f, m;
bool check(double i, double j, double k) {
	double j3 = 360 * k / 60;
	double j2 = 360 * j / 60 +  6 * k / 60;
	double j1 = 360 * i / 12 + 30 * (j * 60 + k) / 3600;
	double A = fabs(j1 - j2), B = fabs(j2 - j3);
	if (A > 180) A = 360 - A;
	if (B > 180) B = 360 - B;
	if (A == 2 * B && A != B) return 1;
	else return 0;
}
int main() {
	for (int i = 0; i <= 6; i++) {
		for (int j = 0; j < 60; j++) {
			for (int k = 0; k < 60; k++) {
				if (check(i, j, k)) {
					cout << i << ' ' << j << ' ' << k << endl;
				}
			}
		}
	}
	return 0;
}

C.卡牌

解题思路:

二分

参考代码:

#include<bits/stdc++.h>  
using namespace std;  
#define ll long long  
const int N = 2e5 + 5;  
ll n, m;  
struct node {  
    int a, b, i;  
} t[N];  
bool cmp(node a, node b) {  
    if (a.a == b.a) return a.b < b.b;  
    return a.a < b.a;  
}  
bool cheak(int x) {  
    ll ans = 0;  
    for (int i = 1; i <= n; i++) {  
        if (x - t[i].a <= t[i].b) {  
            ans += max(0, x - t[i].a);  
        } else return 1;  
    }  
    if (m - ans >= 0) return 0;  
    return 1;  
}  
int find(int l, int r) {  
    int mid;  
    while (l <= r) {  
        mid = (l + r) >> 1;  
        if (cheak(mid)) r = mid - 1;  
        else l = mid + 1;  
    }  
    return l - 1;  
}  
main() {  
    cin >> n >> m;  
    for (int i = 1; i <= n; i++) scanf("%d", &t[i].a);  
    for (int i = 1; i <= n; i++) scanf("%d", &t[i].b);  
    for (int i = 1; i <= n; i++) t[i].i = i;  
    sort(t + 1, t + n + 1, cmp);  
    int an = find(t[1].a, 900000);  
    if (an == 0) {  
        cout << t[1].a;  
        return 0;  
    }  
    cout << an;  
    return 0;  
}  

D.最大数字

解题思路:

使用搜索枚举所有情况

参考代码:

#include<bits/stdc++.h>  
using namespace std;  
#define ll long long  
const int N = 2e5 + 5;  
string s;  
int a, b;  
int n[25], len;  
vector<string>ans;  
void dfs(int k) {  
    if (k > len) {  
        string str;  
        for (int i = 1; i <= len; i++) str.push_back(n[i] + '0');  
        ans.push_back(str);  
        return;  
    }  
    int x = n[k];  
    int y = a;  
    if (a >= 9 - n[k]) {  
        a -= 9 - n[k];  
        n[k] = 9;  
        dfs(k + 1);  
        n[k] = x;  
        a += 9 - n[k];  
    } else {  
        n[k] += a;  
        a = 0;  
        dfs(k + 1);  
        a = y;  
        n[k] = x;  
    }  
    if (b >= n[k] + 1) {  
        b -= n[k] + 1;  
        n[k] = 9;  
        dfs(k + 1);  
        n[k] = x;  
        b += n[k] + 1;  
    } else {  
        if (a >= 9 - n[k]) {  
            a -= 9 - n[k];  
            n[k] = 9;  
            dfs(k + 1);  
            n[k] = x;  
            a += 9 - n[k];  
        } else {  
            n[k] += a;  
            a = 0;  
            dfs(k + 1);  
            a = y;  
            n[k] = x;  
        }  
    }  
}  
int main() {  
    cin >> s >> a >> b;  
    len = s.size();  
    for (int i = 1; i <= len; i++) n[i] = s[i - 1] - '0';  
    dfs(1);  
    cout << *max_element(ans.begin(), ans.end());  
    return 0;  
}  

E.出差

解题思路:

图论最短路,处理一下边权,直接套模板

参考代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e3 + 5;
#define inf 0x3f3f3f3f
int n, m;
int g[N][N];
int dis[N];
bool is[N];
int c[N];
void Dijkstra() {
	for (int i = 1; i <= n; i++) dis[i] = g[1][i];
	dis[1] = 0;
	is[1] = 1;
	for (int i = 1; i <= n; i++) {
		int k = 0;
		for (int j = 1; j <= n; j++) {
			if (is[j] == 0 && (k == 0 || dis[j] < dis[k])) k = j;
		}
		is[k] = 1;
		for (int j = 1; j <= n; j++) {
			dis[j] = min(dis[j], dis[k] + g[k][j]);
		}
	}
}
int main() {
	memset(g, inf, sizeof(g));
	cin >> n >> m;
	for (int i = 1; i <= n; i++) cin >> c[i];
	int u, v, w;
	for (int i = 1; i <= m; i++) {
		cin >> u >> v >> w;
		g[u][v] = w + c[v];
		g[v][u] = w + c[u];
	}
	Dijkstra();
	cout << dis[n] - c[n];
	return 0;
}

F.费用报销

解题思路:

01背包,直接套板子

参考代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 5;
int mday[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int sday[13];

int n, m, k;
struct node {
	int m, d, v;
	int sum;
	void init() {
		sum = sday[m - 1] + d;
	}
} a[N];
int f[N];
int dp[N][N * 5];
bool cmp(node a, node b) {
	return a.sum < b.sum;
}

int main() {
	for (int i = 1; i <= 12; i++) sday[i] = sday[i - 1] + mday[i];
	cin >> n >> m >> k;
	for (int i = 1; i <= n; i++) cin >> a[i].m >> a[i].d >> a[i].v, a[i].init();
	sort(a + 1, a + 1 + n, cmp);
	a[0].sum = -500;

	for (int i = 1; i <= n; i++) {
		for (int j = 0; j < i; j++) {
			if (a[i].sum - a[j].sum >= k) f[i] = j;
		}
	}

	for (int i = 1; i <= n; i++) {
		for (int j = 0; j <= m; j++) {
			dp[i][j] = dp[i - 1][j];
			if (j - a[i].v >= 0) dp[i][j] = max(dp[i][j], dp[f[i]][j - a[i].v] + a[i].v);
		}
	}

	cout << dp[n][m];
	return 0;
}

G.故障

解题思路:

参考代码:

H.机房

解题思路:

dis_i 表示根节点到节点i的距离,cnt_i 表示节点i的权值,那么对于两点x,y,他们的最短路时间为dis_x+dis_y-dis_{lca(x,y)}*2+cnt_{lca(x,y)}

参考代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e5 + 5;
vector<int>g[N];
ll dis[N], deep[N], f[N][25], cnt[N];
int n, m;
void init(int u, int fa, ll dist) {
	deep[u] = deep[fa] + 1;
	f[u][0] = fa;
	dis[u] = dist;
	for (int i = 1; (1 << i) <= deep[u]; i++) {
		f[u][i] = f[f[u][i - 1]][i - 1];
	}
	for (int i = 0; i < g[u].size(); i++) {
		if (g[u][i] == fa) continue;
		else init(g[u][i], u, dist + cnt[g[u][i]]);
	}
}
int lca(int x, int y) {
	if (deep[x] < deep[y]) swap(x, y);
	for (int i = 20; i >= 0; i--) {
		if (deep[f[x][i]] >= deep[y]) x = f[x][i];
		if (x == y) return x;
	}
	for (int i = 20; i >= 0; i--) {
		if (f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
	}
	return f[x][0];
}

inline ll get(int x, int y) {
	return dis[x] + dis[y] - dis[lca(x, y)] * 2 + cnt[lca(x, y)];
}
int main() {
	cin >> n >> m;
	int u, v;
	for (int i = 1; i < n; i++) {
		cin >> u >> v;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	for (int i = 1; i <= n; i++) cnt[i] = g[i].size();
	init(1, 0, cnt[1]);
	for (int i = 1; i <= m; i++) {
		cin >> u >> v;
		cout << get(u, v) << endl;
	}
	return 0;
}

I. 齿轮

解题思路:

参考代码:

#include<bits/stdc++.h>  
using namespace std;  
#define ll long long  
const int N = 2e5 + 5;  
int n, q, p;  
int ma;  
int r[N];  
bool is[N];  
int t[N];  
void init() {  
    for (int i = 1; i <= n; i++) {  
        for (int j = 1; j * r[i] <= ma; j++) {  
            if (t[j * r[i]]) is[j] = 1;  
        }  
    }  
}  
int main() {  
    cin >> n >> q;  
    for (int i = 1; i <= n; i++) {  
        scanf("%d", &r[i]);  
        ma = max(ma, r[i]);  
        t[r[i]]++;  
    }  
    init();  
    for (int i = 1; i <= q; i++) {  
        cin >> p;  
        if (is[p]) printf("YES\n");  
        else printf("NO\n");  
    }  
    return 0;  
}  

J.搬砖

解题思路:

参考代码:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值