第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;
}
相关推荐
雪落漂泊4 分钟前
C++11(上)
开发语言·c++
青山木19 分钟前
Hot 100 --- 最长递增子序列
java·数据结构·算法·leetcode·动态规划
土司大王1 小时前
LeetCode hot100——33.搜索旋转排序数组:Java 二分模板与 O(log n) 实现
数据结构·算法·leetcode
不穿鞋的懒羊羊1 小时前
STL容器
算法
huang5791471 小时前
多线程环境下的共享数据结构安全问题分析4
算法
zh路西法1 小时前
【玩转VLA具身智能机械臂】(四):点云分割与 OBB 夹取——从 PCA 失效到主动扫描
c++·机械臂·pca·vla·planner·obb·moveit2
地平线开发者1 小时前
模型部署|征程6 量化路线怎么选:PTQ 还是 QAT?
神经网络·算法·机器学习
程序员阿鹏1 小时前
如何实现MySQL分库分表?
数据结构·数据库·sql·mysql·缓存
不会就选b2 小时前
算法日常・每日刷题--<贪心>12
算法
爱和冰阔落2 小时前
【Linux】条件变量为什么必须配合互斥锁:从 pthread_cond_wait 到阻塞队列
linux·运维·c++·缓存·中间件·安卓