第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;
}
相关推荐
fqbqrr7 小时前
2606C++,C++构的多态
开发语言·c++
小欣加油7 小时前
leetcode56 合并区间
c++·算法·leetcode·职场和发展
lqqjuly7 小时前
前沿算法深度解析(二)
人工智能·算法·机器学习
Yolo_TvT8 小时前
C++:析构函数
c++
徐小夕9 小时前
万字长文!千万级文档 RAG 知识库系统落地实践
前端·算法·github
akunkuntaimei9 小时前
2026年高考数学各省真题及答案(完整版)
算法·高考
Hello:CodeWorld10 小时前
C 风格变参 vs C++ 变参模板:核心区别与选型指南
c语言·c++·算法
8Qi811 小时前
LeetCode 516:最长回文子序列
算法·leetcode·职场和发展·动态规划
十月的皮皮11 小时前
C语言学习笔记20260606- 求月份天数三种写法
c语言·笔记·学习
搬砖魁首12 小时前
基础能力系列 - 多线程2 - 条件变量
c++·rust·条件变量·原子类型·线程同步互斥