第十二届 蓝桥杯C++ B组题解 第一场

A:空间

在这里插入图片描述

B=Byte b=bit
1MB=1024KB
1KB=1024B
1B=8b
32b=4B
256MB=256*1024*1024B
so 256MB/32b=67108864

B:卡片

在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;

int s[10];

bool check(int x)
{
    while (x)
    {
        int t = x % 10;
        x /= 10;
        if (--s[t] < 0)
            return false;
    }
    return true;
}
int main()
{
    for (int i = 0; i < 10; i++)
    {
        s[i] = 2021;
    }

    for (int i = 1;; i++)
    {
        if (!check(i))
        {
            cout << i - 1 << endl;
            system("pause");
            return 0;
        }
    }
    system("pause");
    return 0;
}

C:直线

在这里插入图片描述
解析:斜率和截距可唯一确定一条平面直线,注意斜率不存在的线,注意double特性

#include <bits/stdc++.h>
using namespace std;

const int N = 200000;
int n = 0;
struct Line
{
    double k, b;
    bool operator<(const Line &t) const
    {
        if (k != t.k)
            return k < t.k;
        return b < t.b;
    }
} I[N];

int main()
{
    for (int x1 = 0; x1 < 20; x1++)
    {
        for (int y1 = 0; y1 < 21; y1++)
        {
            for (int x2 = 0; x2 < 20; x2++)
            {
                for (int y2 = 0; y2 < 21; y2++)
                {
                    if (x1 != x2)
                    {
                        double k = (double)(y2 - y1) / (x2 - x1);
                        double b = (double)(y1 - k * x1);
                        I[n++] = {k, b};
                    }
                }
            }
        }
    }
    sort(I, I + n);
    int res = 1;
    for (int i = 1; i < n; i++)
        if (fabs(I[i].k - I[i - 1].k) > 1e-8 || fabs(I[i].b - I[i - 1].b) > 1e-8)
            res++;
    cout << res + 20 << endl;
    system("pause");
    return 0;
}

D:货物摆放

在这里插入图片描述
约数求组合:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

int main()
{
    ll n;
    cin >> n;
    vector<ll> d;
    for (ll i = 1; i * i <= n; i++)
    {
        if (n % i == 0)
        {
            d.push_back(i);
            if (n / i != i)
                d.push_back(n / i);
        }
    }

    int res = 0;
    for (auto a : d)
    {
        for (auto b : d)
        {
            for (auto c : d)
            {
                if (a * b * c == n)
                {
                    res++;
                }
            }
        }
    }
    cout << res << endl;
    system("pause");
    return 0;
}//2430

暴力模拟+剪枝:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

int main()
{
    ll n;
    cin >> n;
    int res = 0;
    for (ll i = 1; i * i * i <= n; i++)
    {
        if (n % i == 0)
        {
            for (ll j = i; i * j * j <= n; j++)
            {
                if (n / i % j == 0)
                {
                    ll k = n / i / j;
                    if (i == j && j == k)
                        res++;
                    else if (i != j && j != k)
                    {
                        res += 6;
                    }
                    else
                    {
                        res += 3;
                    }
                }
            }
        }
    }
    cout << res << endl;
    system("pause");
    return 0;
}

E:路径

在这里插入图片描述
动态滚动:

#include <bits/stdc++.h>
using namespace std;
int dp[2021];//表示到1的距离

int lcm(int a, int b)
{
    return a / __gcd(a, b) * b;
}

void init()//初始化
{
    for (int i = 1; i <= 2021; i++)
    {
        dp[i] = 20212021;//INF
    }
}
int main()
{
    init();
    dp[1] = 0;
    for (int i = 2; i <= 22; i++)
    {
        dp[i] = i;
    }
    for (int i = 2; i <= 2021; i++)
    {
        for (int k = 1; k <= 21; k++)
        {
            if ((i - k) >= 1)
            {
                dp[i] = min(dp[i], dp[i - k] + lcm(i - k, i));
            }
        }
    }
    cout << dp[2021] << endl;
    system("pause");
    return 0;
}//10266837

F:时间显示

在这里插入图片描述

1秒==1000ms
不知道也没关系,样例给的好,可以试出来

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
    ll n;
    cin >> n;
    n /= 1000;
    n %= 86400;
    int h = n / 3600;
    n %= 3600;
    int m = n / 60;
    int s = n % 60;
    printf("%02d:%02d:%02d", h, m, s);
    system("pause");
    return 0;
}

G:砝码称重

在这里插入图片描述
在这里插入图片描述

本人超喜欢喜欢bitset

#include <bits/stdc++.h>
using namespace std;

bitset<200021> ans, tmp;
//0的位置
#define W 100010
//总长度
#define len 200021
int n;
int arr[105];

void moni()
{
    for (int i = 0; i < W; i++)
    {
        if (ans[i])
        {
            ans[len - 1 - i] = 1;
            ans[i] = 0;
        }
    }
}

int main()
{
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        cin >> arr[i];
    }
    ans[W] = 1;
    for (int i = 0; i < n; i++)
    {
        tmp.reset();
        tmp[W] = 1;
        tmp = tmp | (ans << arr[i]);
        tmp = tmp | (ans >> arr[i]);
        ans = ans | tmp;
        moni();
    }
    cout << ans.count() - 1 << endl;
    system("pause");
    return 0;
}

H:杨辉三角形

在这里插入图片描述

偶数行的个数是奇数个,其中最中间的数是最大的,也是“跑”的最快的,如果一个目标值比增长最快的数还大的话,就往后所在的斜行找

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n;

ll C(int a, int b)
{
    ll res = 1;
    for (int i = a, j = 1; j <= b; i--, j++)
    {
        res = res * i / j;
        if (res > n)
            return res;
    }
    return res;
}
bool check(int k)
{
    ll l = 2 * k, r = n;
    while (l < r)
    {
        ll mid = l + r >> 1;
        if (C(mid, k) >= n)
            r = mid;
        else
            l = mid + 1;
    }
    if (C(r, k) != n)
        return false;
    cout << r * (r + 1) / 2 + k + 1;
    return true;
}

int main()
{
    cin >> n;
    for (int k = 16;; k--)
    {
        if (check(k))
            break;
    }
    system("pause");
    return 0;
}

I:双向排序

![在这里插入图片描述](https://img-blog.csdnimg.cn/2021050916031864.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L01vUmFuMF8w,size_16,color_FFFFFF,t_70

#include <iostream>

#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;

const int N = 100010;

int n, m;
PII stk[N];//第一关键词存什么操作,第二关键词存操作下标
int ans[N];

int main()
{
    cin >> n >> m;
    int tt = 0;
    while (m -- )
    {
        int p, q;
        cin >> p >> q;
        if (!p) //前缀操作
        {
            while (tt && stk[tt].x == 0) q = max(q, stk[tt -- ].y); //对于连续的前缀操作,保留最长的
            while (tt >= 2 && stk[tt - 1].y <= q) tt -= 2; //直至遇到后缀操作,删除前面所有长度比当前小的前缀操作(以及与之配套的后缀操作)
            stk[ ++ tt] = {0, q};
        }
        else if (tt)//后缀操作,第一个操作一定不是后缀操作 
        {
            while (tt && stk[tt].x == 1) q = min(q, stk[tt -- ].y);
            while (tt >= 2 && stk[tt - 1].y >= q) tt -= 2;
            stk[ ++ tt] = {1, q};
        }
    }

    //处理操作,每次都是缩小端点
    int k = n, l = 1, r = n;
    for (int i = 1; i <= tt; i ++ )
    {
        if (stk[i].x == 0) //前缀操作,前缀操作端点后面的已经确定(从n开始递减)
            while (r > stk[i].y && l <= r) ans[r -- ] = k -- ;
        else //后缀操作,后缀操作端点前面的已经确定(继续递减)    
            while (l < stk[i].y && l <= r) ans[l ++ ] = k -- ;
        if (l > r) break;
    }   

    //处理最后一次操作,这次操作是真操作,端点两边已经动完了
    if (tt % 2) //最后一次操作是前缀操作
        while (l <= r) ans[l ++ ] = k -- ;
    else //最后一次操作是后缀操作
        while (l <= r) ans[r -- ] = k -- ;

    for (int i = 1; i <= n; i ++ )
        cout << ans[i] << ' ';
    cout << endl;

    return 0;
}

J:扩号序列

在这里插入图片描述

#include <algorithm>
#include <cstring>
#include <iostream>

using namespace std;

typedef long long LL;

const int N = 5010, MOD = 1e9 + 7;

int n;
char str[N];
LL f[N][N];

LL work()
{
    memset(f, 0, sizeof f);
    f[0][0] = 1;
    for (int i = 1; i <= n; i++)
        if (str[i] == '(')
        {
            for (int j = 1; j <= n; j++)
                f[i][j] = f[i - 1][j - 1];
        }
        else
        {
            f[i][0] = (f[i - 1][0] + f[i - 1][1]) % MOD;
            for (int j = 1; j <= n; j++)
                f[i][j] = (f[i - 1][j + 1] + f[i][j - 1]) % MOD;
        }

    for (int i = 0; i <= n; i++)
        if (f[n][i])
            return f[n][i];
    return -1;
}

int main()
{
    scanf("%s", str + 1);
    n = strlen(str + 1);
    LL l = work();
    reverse(str + 1, str + n + 1);
    for (int i = 1; i <= n; i++)
        if (str[i] == '(')
            str[i] = ')';
        else
            str[i] = '(';
    LL r = work();
    printf("%lld\n", l * r % MOD);
    system("pausse");
    return 0;
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

.0-0.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值