第十七届蓝桥杯C/C++A组省赛

前几天,蓝桥杯国赛的成绩出了,拿了国三,有点小遗憾但也在预料之内吧

不过成绩出了不代表都结束了,还是要复盘,就从省赛开始吧,省赛我拿了是省一,但是回过头来才发现其实还是有不少不会的地方,所以来总结一下吧,这次就不发截图了,直接给洛谷上的链接吧

A题:均衡数

由于 2026202620262026 的二进制有 51 位,且一个均衡数的二进制长度必须是偶数,故我们只需要构造二进制为 50 位的最大的均衡数,以及二进制为 52 位最小的均衡数。

想要最大我们就要让尽量让高位是 1,低位是 0。想要最小我们就要让尽量让高位是 0,低位是 1。但最高位不能为 0。所以我们只要让最高位是 1,后面跟 26 个 0,最后再跟 25 个 1 就行。

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
	cout<<2251799847239679<<endl;
	return 0;
}

C题:拦截系统

这个也比较简单,签到题吧

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL l,t,v;
int main()
{
	int n;
	cin>>n;
	while(n--)
	{
		cin>>l>>t>>v;
		LL s=t*v*2;
		l-=s;
		cout<<l/2+l%2<<endl;
	}
	return 0;
}

D题:切割木材

这个就是比较经典的二分嘛

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
typedef long long LL;
LL a[N];
LL n,k;
bool check(int x)
{
	LL res=0;
	for(int i=1;i<=n;i++)
	{
		res+=a[i]/x-1+(a[i]%x!=0);
	}
	return res<=k;
}
int main()
{
	cin>>n>>k;
	LL l=0,r=0;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		r=max(r,a[i]);
	}
	LL ans=-1;
	while(l<=r)
	{
		//cout<<l<<' '<<r<<endl;
		LL mid=l+r>>1;
		if(!check(mid))
		{
			l=mid+1;
		}
		else
		{
			ans=mid;
			r=mid-1;
		}
	}
	cout<<ans<<endl;
	return 0;
}

E题:读取指令

这个题,我一开始以为挺简单,以为就是个简单贪心,刚才做了一下才发现是比赛时做错了,这是一个数学问题

首先如果 w 不是 c 的倍数肯定 −1,否则令 x=cw​。

如果 1+2+⋯+n=2n(n+1)​<x,也是无解。

如果 w=0,答案是 0。(赛时代码好像没考虑这个,寄)

否则,下面证明答案最多是 2。

由于 2n(n+1)​≥x,因此一定存在一个 1≤m<n,使得:

  • 1+2+⋯+m=2m(m+1)≤x;
  • 1+2+⋯+(m+1)>x。

我们可以证明 y=1+2+⋯+(m+1)−x=(m+1)−x−(1+2+⋯m)≤(m+1),我们把 (m+1) 补上,再把 y 删去,最多两个区间。

所以答案不是 1 就是 2。开 map 记录一下前缀和,即可判断一个区间是否可行,可行则为 1,否则为 2。

cpp 复制代码
#include <iostream>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int T;
    cin >> T;
    while (T--) {
        int N, C;
        long long W;
        cin >> N >> C >> W;

        // 边界1:不需要读取
        if (W == 0) {
            cout << "0\n";
            continue;
        }
        // 边界2:无法整除C,无解
        if (W % C != 0) {
            cout << "-1\n";
            continue;
        }

        long long x = W / C;
        long long total = (long long)N * (N + 1) / 2;
        // 边界3:总和不足,无解
        if (x > total) {
            cout << "-1\n";
            continue;
        }

        // 双指针判断是否存在单个连续区间和为x
        long long sum = 0;
        int l = 1;
        bool found = false;
        for (int r = 1; r <= N; ++r) {
            sum += r;
            while (sum > x) {
                sum -= l;
                l++;
            }
            if (sum == x) {
                found = true;
                break;
            }
        }

        cout << (found ? 1 : 2) << '\n';
    }
    return 0;
}

F题:外卖配送

考虑使用动态规划。

  • 状态定义: fi 表示送 i 单所需的时间;
  • 状态转移: fi←fj+ci−j+x,其中 ci 表示单个交通工具送完 i 单所需的最短时间,j 是枚举的单数;
  • 最终答案:fn。
cpp 复制代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n, m, x, f[5005], c[5005];
signed main() {
    memset(c, 0x3f, sizeof c);
    cin >> n >> m >> x;
    for (int i = 1, a, b; i <= m; ++i) {
        cin >> a >> b;
        for (int j = 1; j <= n; ++j) {
            c[j] = min(c[j], j * a + j * (j - 1) / 2 * b); // 预处理
        }
    }
    for (int i = 1; i <= n; ++i) {
        f[i] = c[i];
        for (int j = 1; j < i; ++j) {
            f[i] = min(f[i], f[j] + c[i - j] + x); // 状态转移
        }
    }
    cout << f[n];
    return 0;
}

好的,现在比赛中黄题难度及以下,以及我比赛时会的题目就已经说完了,这些题如果都拿下其实就能稳稳省一了,我现在回过头来发现,我当时应该就是A,C,D,F题做对了,G暴力得了一半分,拿了省一

相关推荐
想你依然心痛2 分钟前
嵌入式C代码规范:MISRA-C 2012核心规则解读——类型安全与未定义行为深度剖析
c语言·安全·代码规范
mingo_敏24 分钟前
Mean-Teacher 均值教师自训练框架详解
算法·均值算法
会周易的程序员40 分钟前
microLog 后端开发指南
开发语言·c++·物联网·设计模式·日志·iot·aiot
星空露珠1 小时前
迷你世界UGc3.0脚本Wiki[剧情动画模块管理接口 Timeline]
开发语言·数据结构·算法·游戏·lua
笨笨没好名字1 小时前
Leetcode刷题python3版第一周(下)
linux·算法·leetcode
汉克老师1 小时前
GESP2026年6月认证C++二级( 第三部分编程题(2、菱形))精讲
c++·找规律·绘制图形·对角线·双重循环
手写码匠1 小时前
手写 LLM 安全护栏:从内容审核到越狱防御的完整实现
人工智能·深度学习·算法·aigc
未来之窗软件服务1 小时前
计算机考试-C语言 应用题—东方仙盟
c语言·开发语言·仙盟创梦ide·东方仙盟·计算机考试
luj_17681 小时前
草酸与烟酸对消化及糖代谢的影响解析
服务器·c语言·开发语言·经验分享·算法
fei_sun1 小时前
【SystemVerilog】SystemVerilog与C语言的接口
c语言·开发语言