2025年第十六届蓝桥杯国赛C/C++大学B组个人题解

写在前面

今年国赛刚刚结束,忍不住抒发一下感想。主要就是一个重大失误和一个创造奇迹。

题解和代码(回忆版)

两道填空题一眼没思路,直接看编程题,后面也没时间再看了,扫了一眼感觉不好蒙,就空着了。

试题 C: 数字轮盘

我是在草稿纸上手动模拟来找规律,写了一页A4纸大小的草稿,花了一个半小时之久。可以发现,“操作”的作用就是将最后两个数字移到最前面。接着想办法把各种情况对应过去即可。注意,当 n 为偶数而  k 为奇数时,无法恢复原样。

#include <iostream>

using namespace std;

void solve()
{
	int n,k;
	cin>>n>>k;

	if(k%n==0)
	{
		cout<<0<<'\n';
		return;
	}

	if(n%2==1)
	{
		if(k%n%2==0) cout<<(2*n-k%n)/2;
		else cout<<(n-k%n)/2;
		cout<<'\n';
	}
	else
	{
		if(k%2==1)
		{
			cout<<-1<<'\n';
			return;
		}

		cout<<(n-k%n)/2<<'\n';
	}
}

int main()
{
    int t;
    cin>>t;
    while(t--)
	{
		solve();
	}
    return 0;
}


在洛谷跑的是满分,应该问题不大。

试题 D: 斐波那契字符串

这题思路还是挺简单的,看代码即可了解,是动态规划的思想。当然,我做的时候没想什么动态规划,当成思维题做了。

然而我犯了一个重大错误。代码如下。

#include <iostream>
#define int long long
using namespace std;

const int N = 1e9 + 7;

void solve()
{
    int n;
    cin >> n;
    int a_cnt0 = 1, a_cnt1 = 0, a_sum = 0;
    int b_cnt0 = 0, b_cnt1 = 1, b_sum = 0;
    int cnt0 = 0, cnt1 = 0, sum = 0;
    for (int i = 3; i <= n; ++i)
    {
        cnt0 = (a_cnt0 + b_cnt0) % N;
        cnt1 = (a_cnt1 + b_cnt1) % N;

        sum = (a_sum + b_sum + a_cnt1 * b_cnt0 % N) % N;

        a_cnt0 = b_cnt0;
        a_cnt1 = b_cnt1;
        a_sum = b_sum;

        b_cnt0 = cnt0;
        b_cnt1 = cnt1;
        b_sum = sum;
    }
    cout << sum << '\n';
}

signed main()
{
    int t;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

只拿到四分之一的分,其他都超时了。问题在于,我每个测试用例都跑了一遍循环,没有想到可以先把数据范围内的所有答案跑出来存起来,这样对于每个用例,只需把答案取出来,大大节省时间。

我当时以为所有测试用例的 N 的总和不超过 10^{^{5}} ,可能是受cf题目影响,有惯性思维了。但是蓝桥杯的这道题并不是这个意思,因此我这样写就超时了,因为 T 最大能到 10^{^{5}} ,乘起来就是很大的数了。

修改后的代码如下。洛谷满分。

#include <iostream>
#define int long long
using namespace std;

const int N = 1e9 + 7;

int a[100005];

void init()
{
    int a_cnt0 = 1, a_cnt1 = 0, a_sum = 0;
    int b_cnt0 = 0, b_cnt1 = 1, b_sum = 0;
    int cnt0 = 0, cnt1 = 0, sum = 0;
    for (int i = 3; i <= 100000; ++i)
    {
        cnt0 = (a_cnt0 + b_cnt0) % N;
        cnt1 = (a_cnt1 + b_cnt1) % N;

        sum = (a_sum + b_sum + a_cnt1 * b_cnt0 % N) % N;

        a[i] = sum;

        a_cnt0 = b_cnt0;
        a_cnt1 = b_cnt1;
        a_sum = b_sum;

        b_cnt0 = cnt0;
        b_cnt1 = cnt1;
        b_sum = sum;
    }
}

void solve()
{
    int n;
    cin >> n;
    cout << a[n] << '\n';
}

signed main()
{
    int t;
    cin >> t;
    init();
    while (t--)
    {
        solve();
    }
    return 0;
}

试题 E: 项链排列

这道题我是用全排列函数找规律。应该算是构造题。

#include <iostream>
#include <string>
using namespace std;

void solve()
{
    int a, b, c;
    cin >> a >> b >> c;

    string s = "";

    if (c == 0) //特判
    {
        if (a == 0)
        {
            for (int i = 1; i <= b; ++i) s += "Q";
            cout << s;
            return;
        }
        else if (b == 0)
        {
            for (int i = 1; i <= a; ++i) s += "L";
            cout << s;
            return;
        }
        else
        {
            cout << -1;
            return;
        }
    }

    if (a == b)
    {
        if (c > a + b - 1)
        {
            cout << -1;
            return;
        }
        if (c == a + b - 1)
        {
            for (int i = 1; i <= a + b; ++i)
            {
                if (i & 1) s += "L";
                else s += "Q";
            }
            cout << s;
            return;
        }
    }
    else
    {
        if (c > min(a, b) * 2)
        {
            cout << -1;
            return;
        }
        if (c == min(a, b) * 2)
        {
            if (a > b)
            {
                for (int i = 1; i <= a - b - 1; ++i) s += "L";
                for (int i = 1; i <= b * 2 + 1; ++i)
                {
                    if (i & 1) s += "L";
                    else s += "Q";
                }
                cout << s;
                return;
            }
            else
            {
                for (int i = 1; i <= a * 2 + 1; ++i)
                {
                    if (i & 1) s += "Q";
                    else s += "L";
                }
                for (int i = 1; i <= b - a - 1; ++i) s += "Q";
                cout << s;
                return;
            }
        }
    }

    if (c % 2 == 0)
    {
        for (int i = 1; i <= a - c / 2 - 1; ++i) s += "L";
        for (int i = 1; i <= c; ++i)
        {
            if (i & 1) s += "L";
            else s += "Q";
        }
        for (int i = 1; i <= b - c / 2; ++i) s += "Q";
        s += "L";
        cout << s;
    }
    else
    {
        c = (c + 1) / 2;
        for (int i = 1; i <= a - c; ++i) s += "L";
        for (int i = 1; i <= c * 2; ++i)
        {
            if (i & 1) s += "L";
            else s += "Q";
        }
        for (int i = 1; i <= b - c; ++i) s += "Q";
        cout << s;
    }
}

int main()
{
    int t = 1;
    //cin>>t;
    while (t--)
    {
        solve();
    }
    return 0;
}


代码里 c=0 的特判我当时没想到,如果两种珠子数量都大于零,那么 c 就不能为零。比赛的时候光想着判断最大值了,推着推着就忘记最小值了。没加特判前,洛谷跑了95分,加上之后满分。

试题 F: 蓝桥星数字

看到这道题的时候,应该是没多少时间了,急忙写了个暴力。

#include <iostream>
#define int long long
using namespace std;

bool check(int n)
{
    if (n < 10) return 0;
    int m = n, c1, c2;
    c1 = m % 10;
    m /= 10;
    while (m > 0)
    {
        c2 = m % 10;
        if ((c1 % 2) == (c2 % 2)) return 0;
        m /= 10;
        c1 = c2;
    }
    return 1;
}

void solve()
{
    int n;
    cin >> n;
    int i = 1, j = 0;
    for (;; ++i)
    {
        if (check(i))
        {
            ++j;
            if (j == n)
            {
                break;
            }
        }
    }
    cout << i;
}

signed main()
{
    int t = 1;
    //cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

洛谷20分,其他样例都超时。

试题 G: 翻倍

这个时候只剩十分钟左右了,我都准备开摆了,但是瞄了一眼题目,感觉应该可以快速敲个暴力,于是立马动手,大概花了五分钟吧,真的极限,不知道官方测试数据水不水,在洛谷能骗一半分。

#include <iostream>
#define int long long
using namespace std;

int a[200005];

void solve()
{
    int n;
    cin >> n;
    for (int i = 1; i <= n; ++i)
	{
		cin >> a[i];
	}
    int cnt = 0;
    for (int i = 2; i <= n; ++i)
    {
        while (a[i] < a[i - 1])
        {
            ++cnt;
            a[i] *= 2;
        }
    }
    cout << cnt;
}

signed main()
{
    int t = 1;
    //cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

我感觉这个真的是创造奇迹,手感来了挡都挡不住。

剩下的题目也没时间看了,大致扫一眼,感觉也没法直接输出东西来骗分,就空着了。

总结

这几个月基本没怎么做题,因此没有手感,D题犯下重大错误。不知道是不是为了弥补这个错误,做了几个小时后手感上来,G题“神救场”。其实归根结底还是要通过努力来提高实力,毕竟这是最能掌握在自己手里的。

结合洛谷,估分大概40,希望有个国三吧。没想到国赛是十道题,满分150,区分度很高。

另外,我想夸一下这次的考点——广州华南商贸职业学院,体验非常好!老师、学生、志愿者、饭堂员工等等,都非常友善。非常感谢各方人员尽力为蓝桥杯国赛保驾护航,希望他们工作顺利、生活愉快!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Washington2022

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值