第16届国赛蓝桥杯大赛C/C++大学C组

目录

一.最大周长

1.题目讲解

2.代码实现

二.拔河

1.题目讲解

2.代码实现

三.铺设能源管道

1.题目讲解

2.代码实现

四.打破规则

1.题目讲解

2.代码实现

五.数字配对

1.题目讲解

2.代码实现

六.宗门大比

1.题目讲解

2.代码实现

七.数列染色

1.题目讲解

2.代码实现

八.正方形构造

1.题目讲解

2.代码实现

九.杨辉三角

1.题目讲解

2.代码实现

十.整齐的数

1.题目讲解

2.代码实现


一.最大周长

题目链接:https://www.lanqiao.cn/problems/21224/learning/

1.题目讲解

或者我们可以直接使用结论(长度变长,宽度小 => 周长最长)

2.代码实现

cpp 复制代码
#include <iostream>

using namespace std;

int main()
{
    int ret = 0;
    for(int i = 1;i <= 2025;i++)
    {
        if(2025 % i == 0)
        {
            ret = max(ret,(i + 2025 / i) * 2);
        }
    }
    cout << ret << endl;
    return 0;
}

二.拔河

题目链接:https://www.lanqiao.cn/problems/21223/learning/

1.题目讲解

2.代码实现

cpp 复制代码
#include <iostream>
#include <algorithm>

using namespace std;

#define int long long
const int N = 1 << 21;

int a[] = {0, 345590635693812, 411735179294186, 190029355501347, 973598561303630,
          18202819016954, 739089526396984, 41064501651340, 287075700776565,
          458062562307032, 723278851371706, 997720296178889, 470475557480472,
          329586527903215, 907379737442406, 631284976214798, 301204036247736,
          747294692547790, 914091289062262, 144070679727924, 988094642462741,
          413975599277375, 835461430976017, 344371572186185, 646160866308904,
          880407857470630, 794629069521762, 462180977651587, 342038139286302,
          854772507978666, 694223418935656, 567502001946067, 881035713848915,
          840605474892139, 324727089144326, 226008847101330, 65143946718125,
          499249957077991, 245803813100131, 447887480320685, 658036302578844
        };

int x[N],c1,y[N],c2;

void ldfs(int pos,int sum)
{
    if(pos > 20)
    {
        x[++c1] = sum;
        return;
    }
    ldfs(pos + 1,sum + a[pos]);
    ldfs(pos + 1,sum - a[pos]);
}

void rdfs(int pos,int sum)
{
    if(pos > 40)
    {
        y[++c2] = sum;
        return;
    }
    rdfs(pos + 1,sum + a[pos]);
    rdfs(pos + 1,sum - a[pos]);
}

signed main()
{
    ldfs(1,0);
    rdfs(21,0);
    sort(x + 1,x + c1 + 1);
    sort(y + 1,y + c2 + 1);

    int ret = 1e18;
    for(int i = 1,j = c2;i <= c1;i++)
    {
        while(j >= 2 && x[i] + y[j - 1] >= 0)
        {
            j--;
        }
        ret = min(ret,abs(x[i] + y[j]));
        if(j >= 2)
        {
            ret = min(ret,abs(x[i] + y[j - 1]));
        }
    }
    cout << ret << endl;
    return 0;
}

三.铺设能源管道

题目链接:https://www.lanqiao.cn/problems/21267/learning/

1.题目讲解

我们能看到 1 / 10 / 100 / 1000 / 10000等数的花费是最小的

2.代码实现

cpp 复制代码
#include <iostream>

using namespace std;

int main()
{
    int n;
    cin >> n;
    int ret = 1;
    while(ret < n)
    {
        ret *= 10;
    }
    cout << ret << endl;
    return 0;
}

四.打破规则

题目链接:https://www.lanqiao.cn/problems/21268/learning/

1.题目讲解

2.代码实现

cpp 复制代码
#include <iostream>

using namespace std;

int main()
{
    int a,b,c;
    cin >> a >> b >> c;
    if(a == b || a == c || c == b || (a > b && b > c) || (a < b && b < c))
    {
        cout << 0 << endl;
    }
    else
    {
        cout << min(min(abs(a - b),abs(a - c)),abs(b - c)) << endl;
    }
    return 0;
}

五.数字配对

题目链接:https://www.lanqiao.cn/problems/21211/learning/

1.题目讲解

2.代码实现

cpp 复制代码
#include <iostream>
#include <vector>

using namespace std;

const int N = 1e6 + 10;

int n,m;
vector<int> p[N];

int main()
{
    cin >> n;
    for(int i = 1;i <= n;i++)
    {
        int x;
        cin >> x;
        p[x].push_back(i);
        m = max(m,x);
    }
    int cnt = 0;
    for(int x = 1;x < m;x++)
    {
        if(p[x].empty() || p[x + 1].empty())
        {
            continue;
        }
        int i = p[x].size() - 1,j = p[x + 1].size() - 1;
        while(i >= 0 && j >= 0)
        {
            if(p[x][i] < p[x + 1][j])
            {
                cnt++;
                i--;
                j--;
                p[x + 1].pop_back();
            }
            else
            {
                i--;
            }
        }
    }
    cout << cnt << endl;
    return 0;
}

六.宗门大比

题目链接:https://www.lanqiao.cn/problems/21221/learning/

1.题目讲解

然后将其差值进行排序即可

2.代码实现

cpp 复制代码
#include <iostream>
#include <algprithm>

using namespace std;

const int N = 5e5 + 10;
int n,m,k,a[N],mx;
int d[N],tot,num;

int main()
{
    cin >> n >> m >> k;
    for(int i = 1;i <= n;i++)
    {
        cin >> a[i];
        mx = max(mx,a[i]);
    }
    if(a[k] == mx)
    {
        for(int i = 1;i < k;i++)
        {
            if(a[i] == mx)
            {
                num++;
            }
        }
        cout << num + 1 << endl;
        return 0;
    }
    for(int i = 1;i <= n;i++)
    {
        if(a[i] == mx)
        {
            num++;
            continue;
        }
        if(a[i] >= a[k] && i < k)
        {
            d[++tot] = a[i] - a[k] + 1;
        }
        if(a[i] > a[k] && i > k)
        {
            d[++tot] = a[i] - a[k];
        }
    }
    num += tot;
    sort(d + 1,d + 1 + tot);
    for(int i = 1;i <= tot;i++)
    {
        if(m >= d[i])
        {
            m -= d[i];
            num--;
        }
    }
    cout << num + 1 << endl;
    return 0;
}

七.数列染色

题目链接:https://www.lanqiao.cn/problems/21219/learning/

1.题目讲解

2.代码实现

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

typedef long long LL;
const int N = 1e5 + 10;

int n, k, a[N];
LL f[N], q[N], h = 1, t;

int main()
{
    cin >> n >> k;
    for (int i = 1; i <= n; i++) 
        cin >> a[i];

    f[1] = a[1];
    for (int i = 2; i <= n; i++)
    {
        // 维护单调队列:队尾弹出比当前值大的元素
        while (h <= t && f[q[t]] >= f[i - 1]) 
            t--;
        // 当前元素下标入队
        q[++t] = i - 1;
        // 队头弹出超出窗口左边界的元素
        if (h <= t && q[h] < i - k - 1) 
            h++;

        // 状态转移:取窗口内最小值 + 当前a[i]
        f[i] = f[q[h]] + a[i];
    }

    cout << f[n] << endl;

    return 0;
}

八.正方形构造

题目链接:https://www.lanqiao.cn/problems/21210/learning/

1.题目讲解

2.代码实现

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

typedef long long LL;
const int N = 1010, mod = 1e9 + 7;

int n, m = 1000;
LL cnt[N];

// 排列数 A(n, m) 函数
LL A(LL n, LL m)
{
    LL ret = 1;
    for (int i = 0; i < m; i++) 
        ret = ret * (n - i) % mod;
    return ret;
}

int main()
{
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        int x; cin >> x;
        cnt[x]++;
    }

    LL ret = 0;

    // 情况1:选出两个不同的数,各取2个,再排列
    for (int i = 1; i <= m; i++)
    {
        if (cnt[i] < 2) continue;
        for (int j = i + 1; j <= m; j++)
        {
            if (cnt[j] < 2) continue;
            ret = (ret + A(cnt[i], 2) * A(cnt[j], 2) % mod) % mod;
        }
    }
    ret = ret * 2 % mod;

    // 情况2:选出相同的数,取4个排列
    for (int i = 1; i <= m; i++)
    {
        if (cnt[i] < 4) continue;
        ret = (ret + A(cnt[i], 4)) % mod;
    }

    cout << ret << endl;

    return 0;
}

九.杨辉三角

题目链接:https://www.lanqiao.cn/problems/21212/learning/

1.题目讲解

2.代码实现

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

typedef long long LL;
const int N = 1e5 + 10;

int m, cnt[N];
map<int, int> mp;

int main()
{
    cin >> m;
    for (LL n = 2; n <= m; n++)
    {
        LL c = 1;
        for (LL k = 1; k <= n / 2; k++)
        {
            // C(n, k)
            c = c * (n - k + 1) / k;
            if (c > N) break; // 剪枝

            if (k * 2 == n) 
                cnt[c] += 1;
            else 
                cnt[c] += 2;
        }
    }

    for (int i = 2; i <= m; i++)
        mp[cnt[i]]++;

    for (auto& t : mp)
        cout << t.first << " " << t.second << endl;

    return 0;
}

十.整齐的数

题目链接:https://www.lanqiao.cn/problems/21209/learning/

1.题目讲解

2.代码实现

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

typedef long long LL;
const int N = 20, M = 210;

LL a[N], cnt, n, m;
LL f[N][N][M];

LL dfs(int pos, int prev, int sum, bool limits, bool zero)
{
    if (!pos) 
        return 1;
    if (!limits && !zero && ~f[pos][prev][sum]) 
        return f[pos][prev][sum];

    LL ret = 0;
    LL up = limits ? a[pos] : 9;

    for (int i = 0; i <= up; i++)
    {
        if (zero)
        {
            ret += dfs(pos - 1, i, sum, limits && (i == a[pos]), zero && !i);
        }
        else if (abs(i - prev) + sum <= m)
        {
            ret += dfs(pos - 1, i, sum + abs(i - prev), limits && (i == a[pos]), zero && !i);
        }
    }

    if (!limits && !zero) 
        f[pos][prev][sum] = ret;
    return ret;
}

int main()
{
    cin >> n >> m;

    memset(f, -1, sizeof(f));
    while (n)
    {
        a[++cnt] = n % 10;
        n /= 10;
    }

    cout << dfs(cnt, 0, 0, 1, 1) << endl;

    return 0;
}
相关推荐
可编程芯片开发3 分钟前
基于全阶观测器的三自由度运动系统状态反馈控制simulink建模与仿真
算法
kobesdu4 分钟前
从零推导FAST-LIO的观测雅可比矩阵
人工智能·算法·矩阵
乐思智能科技有限公司29 分钟前
PLECS软件学习使用(二)直流电机基本系统模型
人工智能·算法·机器学习·面试·职场和发展
阿米亚波36 分钟前
【C++ STL】std::unordered_multiset
开发语言·数据结构·c++·笔记·stl
随意起个昵称42 分钟前
贪心模型-Johnson法则
c++·算法
蜡笔小马43 分钟前
【保姆级教程】Windows 下 CGAL 6.2 + VS2022 全流程实战:从源码编译到项目集成(附避坑指南)
c++·cgal
xiaoye-duck1 小时前
《Linux系统编程》Linux 系统多线程(八): C++ 高并发线程池全链路深度解析与从零手撕实现
linux·c++·线程池
旋生万物1 小时前
电磁力 = 螺旋联络的 90° 旋转?麦克斯韦方程组的几何重构
人工智能·python·算法·机器学习·copilot·世界模型·物理ai
余俊晖1 小时前
多模态大模型细粒度视觉理解:Vision-OPD在线策略自蒸馏技术方案概述
人工智能·深度学习·算法·多模态·opd
胖大和尚2 小时前
在C++的类中,是否可以把函数声明成__device__
c++·cuda