【第十二届蓝桥杯第一场真题】【C++B组】【学习笔记】蓝桥杯每日一练day1

day1 哼哼滴冲😤😤😤😤

一想到蓝桥杯还有一个月,自己还在召唤师峡谷,苦练剑魔,青钢影,我就有一种🤗开摆的快乐,(不,亚达哟😭😭😭😭,从今天开始做做真题吧,希望蓝桥杯不要寄🙏

A、空间(5分)

空间 - 蓝桥云课 (lanqiao.cn)

在这里插入图片描述

#include<iostream>
using namespace std;
int main()
{
	cout<<256 * 1024 * 1024 / 4 <<endl;
	return 0;
}
// 答案: 67108864

---------------------------------😎😎😎分割线😎😎😎----------------------------------

1 MB = 1024 KB

1 KB = 1024 B

1 Byte = 8 bit

B、卡片(5分)

卡片 - 蓝桥云课 (lanqiao.cn)
在这里插入图片描述

#include<iostream>
using namespace std;
const int N = 10;
int cnt[N];
int main()
{
    for(int i = 0 ; i <= 9 ; i++) cnt[i] = 2021;
    int res = 1;
    bool  flag = true;
    for(; flag ; res++)
    {
        flag = true;
        auto t = res;
        while(t)
        {
            cnt[t % 10]--;
            if(cnt[t % 10] == 0) 
            {
                flag = false;
                break;
            }
            t /= 10;
        }
    }
    cout<<res - 1<<endl;
}
// 答案: 3181

---------------------------------😎😎😎分割线😎😎😎----------------------------------

直接嗯造

C、直线(10分)

没有发现题目链接😄

在这里插入图片描述

---------------------------------😎😎😎分割线😎😎😎----------------------------------

我有点🐽第一次,没理解题目,所以真的按照样例,画了11条线
在这里插入图片描述

注意double有精度差,我们用斜率 + 截距就行判断,还要加上20条竖线,初始res为1是因为,没有直线和它比较

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 200000;
int n;
struct Line
{
    double k,b;
    bool operator< (const Line &t) const
    {
        if(k != t.k) return k < t.k;
        return b < t.b;
    }

}l[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 = y2 - k * x2;
                        l[n++] = {k,b};
                    }
    sort(l,l + n);
    int res = 1;
    for(int i = 1 ; i < n ; i++)
        if(l[i].k - l[i-1].k > 1e-8 || l[i].b - l[i-1].b > 1e-8)
            res ++;
    cout<<res + 20 <<endl;
    return 0;
}
// 答案:40257

D、货物摆放(10分)

货物摆放 - 蓝桥云课 (lanqiao.cn)
在这里插入图片描述

---------------------------------😎😎😎分割线😎😎😎----------------------------------
先预处理约数…,然后暴力,就完了,之前👴的真暴力做法TLE了😭😭😭,顺便注意下爆int就行

#include <iostream>
#include<vector>
using namespace std;
typedef long long LL;
int main()
{
  LL n = 2021041820210418;
  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;
  return 0;
}
// 答案:2430

E、路径(15分)

路径 - 蓝桥云课 (lanqiao.cn)

在这里插入图片描述

---------------------------------😎😎😎分割线😎😎😎----------------------------------

我们用Dijkstra来做,y总用spfa,👴就是要不一样

#include <iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 2200;
int n,m;
int g[N][N];
int dist[N];
bool st[N];

int gcd(int a,int b)	// 返回最大公约数
{
  return b ? gcd(b, a % b) : a;
}

int dijkstra()
{
    memset(dist,0x3f,sizeof dist);
    dist[1] = 0;

    for(int i = 0 ; i < n - 1 ; i++)
    {
        int t = -1;
        for(int j = 1 ; j <= n  ; j++)
            if(!st[j] && (t == -1 || dist[t] > dist[j]))
                t = j;
        for(int j = 1 ; j <= n ; j++)
            dist[j] = min(dist[j],dist[t]+g[t][j]);
        st[t] = true; 
    }
    if(dist[n] == 0x3f3f3f3f) return -1;
    return dist[n];
}

int main()
{
  n = 2021;
  memset(g,0x3f,sizeof g);
  for(int i = 1 ; i <= n ; i++)
    for(int j = max(1,i - 2) ; j <= min(n,i + 21) ; j++)
    {
        int d = gcd(i , j);
        g[i][j] = i * j / d;	// 嗨呀!原来a和b的最小公倍数等于 a * b 除以它们的最大公约数🤗
    }
  cout<<dijkstra()<<endl;
  return 0;
}
// 答案:10266837

F、时间显示(15分)

时间显示 - 蓝桥云课 (lanqiao.cn)

在这里插入图片描述

【样例输入1】

4680099

【样例输出1】

13:00:00

【样例输入2】

1618708103123

【样例输出2】

01:08:23

【评测用例规模与约定】

​ 对于所有评测用例,给定的时间为不超过 1 0 18 10^{18} 1018的正整数

---------------------------------😎😎😎分割线😎😎😎----------------------------------

正常题,就是注意下会爆int

#include <iostream>
using namespace std;
int main()
{
    long long n;
    cin>>n;
    n /= 1000;
    n  %= (3600 * 24);
    int hours = n / 3600;
    int minutes = n % 3600 / 60; 
    int seconds = n % 60;
    printf("%02d:%02d:%02d",hours,minutes,seconds);
    return 0;
}

G、砝码称重(20分)

砝码称重 - 蓝桥云课 (lanqiao.cn)

在这里插入图片描述

【样例输入】

3
1 4 6

【样例输出】

10

【样例说明】

能称出的10种重量是:1、2、3、4、5、6、7、9、10、11。
1=1
2=6-4(天平一边放6,另一边放4)
3=4-1;
4=4
5=6-1
6=6
7=6+1
9=4+6-1
10=4+6
11=1+4+6

【评测用例规模与约定】

​ 对于 50% 的评测用例,1 ≤ \le N ≤ \le 15;

​ 对于所有的评测用例: 1 ≤ \le N ≤ \le 100,N个砝码总重量不超过100000;

---------------------------------😎😎😎分割线😎😎😎----------------------------------

有限制的选择问题(背包问题)

来到了我们闫氏DP分析法了嗷,集合划分,最后一个砝码放到哪边有三种情况

在这里插入图片描述

之后考虑f[n][1~m]有多少个非空就行(m为总重量),因为j的范围为-m ~ + m 数组没有负数下标,所以我们要加上偏移量B

#include <iostream>
using namespace std;
const int N = 110,M = 200010,B = M / 2;
bool f[N][M];
int w[N];
int n,m;
int main()
{
    cin>>n;
    for(int i = 1 ; i <= n ; i++) cin>>w[i],m += w[i];
    f[0][B] = true;
    for(int i = 1 ; i <= n ; i++)
        for(int j = -m ; j <= m ; j++)
        {
            f[i][j+B] = f[i-1][j+B];
            if(j - w[i] >= -m) f[i][j+B] |= f[i-1][j - w[i] + B];
            if(j + w[i] <= m) f[i][j+B] |= f[i-1][j + w[i] + B];
        }
    int res = 0;
    for(int i = 1 ; i <= m ; i++)
        if(f[n][i+B])
            res++;
    cout<<res<<endl;
    return 0;
}

H、杨辉三角形(20分)

杨辉三角形 - 蓝桥云课 (lanqiao.cn)

在这里插入图片描述

【输入样例】

6

【输出样例】

13

【评测用例规模与约定】

​ 对于 20% 的评测用例,1 ≤ \le N ≤ \le 10;

​ 对于所有的评测用例: 1 ≤ \le N ≤ \le 1000000000;

---------------------------------😎😎😎分割线😎😎😎----------------------------------

找规律题目,因为对称,并且要找的数字是第一次出现的,所以我们只要找左边就行了

在这里插入图片描述

我们不难发现, C 36 17 C_{36}^{17} C3617 就结束了,超过1e9 了,所以枚举1~16行就差不多了,由于是递增的,所以我们可以用二分查查在哪里

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

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 = k * 2 , r = max((LL)n,l);
    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 << endl;
    return true;
}

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

I、双向排序(25分)

双向排序 - 蓝桥云课 (lanqiao.cn)

在这里插入图片描述

【输入样例】

3 3
0 3
1 2
0 2

【输出样例】

3 1 2

【样例说明】

​ 原数列为(1,2,3)

​ 第1步后为(3,2,1)

​ 第2步后为(3,1,2)

第3步后为(3,1,2)。与第2步操作后相同,因为前两个数已经是降序了。

【评测用例规模与约定】

​ 对于 30% 的评测用例,n,m ≤ \le 1000 ;

​ 对于 60% 的评测用例,n,m ≤ \le 5000 ;

​ 对于所有的评测用例: 1 ≤ \le n,m ≤ \le 100000,0 ≤ \le p i p_i pi ≤ \le 1,1 ≤ \le q i q_i qi ≤ \le n 。

---------------------------------😎😎😎分割线😎😎😎----------------------------------

Splay,人已麻,目前对我来说没有学习意义,不如考试sort写暴力,直接开摆🤗

J、括号序列(25分)

括号序列 - 蓝桥云课 (lanqiao.cn)

在这里插入图片描述

【样例输入】

((()

【样例输出】

5

【评测用例规模与约定】

​ 对于 40% 的评测用例,|s| ≤ \le 200 ;

​ 对于所有的评测用例: 1 ≤ \le |s| ≤ \le 5000;

---------------------------------😎😎😎分割线😎😎😎----------------------------------

这题,真叫我写暴力,我都不知道怎么写😥,真哈人

合法的括号序列,需要满足两个条件

  • 左右括号数量相同
  • 任意前缀中,左括号数不小于右括号数

我们会发现,左括号和右括号,可以分开考虑

添加左括号,添加右括号的方案相乘就是答案

如何保证添加方案不重复

在这里插入图片描述

如果我们现在添加左括号,如上图,我们可以以右括号为分界,划分出四个区间。我们规定,只在右括号的前面添加任意多的左括号

闫氏DP开始

在这里插入图片描述

所以

f[i][j] = f[i-1][j+1] + f[i-1][j] + ... + f[i-1][0];

// 优化下
f[i][j-1]=f[i][j]+f[i-1][j-1]+...+f[i-1][0];
// 因此
f[i][j] = f[i-1][j+1] + f[i][j-1];
#include <iostream>
#include <cstring>
#include <algorithm>

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);
    return 0;
}

我的评价是太麻了,真让我考,我真的寄寄了😭😭😭,蓝桥杯一点都不水,🤡是我自己

视频链接

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值