2021蓝桥杯省赛B组(C++)题解

A:卡片

题目描述

小蓝有很多数字卡片,每张卡片上都是数字0 到9。
小蓝准备用这些卡片来拼一些数,他想从1 开始拼出正整数,每拼一个,就保存起来,卡片就不能用来拼其它数了。
小蓝想知道自己能从1 拼到多少。
例如,当小蓝有30 张卡片,其中0 到9 各3 张,则小蓝可以拼出1 到10,但是拼11 时卡片1 已经只有一张了,不够拼出11。
现在小蓝手里有0 到9 的卡片各2021 张,共20210 张,请问小蓝可以从1拼到多少?

解题思路

既然是填空题就直接暴力求解,主要最后的结果-1,因为刚好到该数的时候超过限制值,所以只能拼到该数的前一个数。

代码:

#include 
using namespace std;
int a[20];
int main()
{
    for(int i=0;i<=9;i++)
    {
        a[i]=2021;
    }
    int ans=0;
    int f=0;
    for(int i=1;;i++)
    {
        int j=i;
        while(j)
        {
            if(a[j%10])
                a[j%10]--;
            else
            {
                f=1;
                break;
            }
            j/=10;
        }
        if(f)
        {
            ans=i;
            break;
        }
    }
    cout<

B :空间

题目描述

小蓝准备用256MB 的内存空间开一个数组,数组的每个元素都是32 位二进制整数。
如果不考虑程序占用的空间和维护内存需要的辅助空间,请问256MB 的空间可以存储多少个32 位二进制整数?

解题思路:

这题没什么好说的,学过计组的应该都会。

代码:

#include 
using namespace std;
int main()
{
    cout<<256*1024*1024/4;
    return 0;
}

C. 货物摆放

题目描述

小蓝有一个超大的仓库,可以摆放很多货物。
现在,小蓝有n 箱货物要摆放在仓库,每箱货物都是规则的正方体。
小蓝规定了长、宽、高三个互相垂直的方向,每箱货物的边都必须严格平行于长、宽、高。
小蓝希望所有的货物最终摆成一个大的立方体。即在长、宽、高的方向上分别堆L、W、H 的货物,满足n = L × W × H。
给定n,请问有多少种堆放货物的方案满足要求。
例如,当n = 4 时,有以下6 种方案:1×1×4、1×2×2、1×4×1、2×1×2、2×2×1、4×1×1。
请问,当n = 2021041820210418 (注意有16 位数字)时,总共有多少种
方案?

解题思路:

这些方案中的每一个长宽高都将是n的因子,所以这题就转化为求n的因子,在求出的n的因子中寻找可能的方案数。

代码:

#include 
using namespace std;
long long int a[3031];
long long int n=2021041820210418;
long long int ans=0;
void fun()
{
    for(long long int i=1;i*i<=n;i++)
    {
        if(n%i==0)
        {
            a[ans++]=i;
            if(i*i!=n)
            a[ans++]=n/i;
        }

    }
}
int main()
{
    fun();
    long long int sum=0;
    for(long long int i=0;i

D、直线

题目:

在平面直角坐标系中,两点可以确定一条直线。
如果有多点在一条直线上,那么这些点中任意两点确定的直线是同一条。
给定平面上2 × 3 个整点{(x, y)|0 ≤ x < 2, 0 ≤ y < 3, x ∈ Z, y ∈ Z},
即横坐标是0 到1 (包含0 和1) 之间的整数、纵坐标是0 到2 (包含0 和2) 之间的整数的点。
这些点一共确定了11 条不同的直线。
给定平面上20 × 21 个整点{(x, y)|0 ≤ x < 20, 0 ≤ y < 21, x ∈ Z, y ∈ Z},
即横坐标是0 到19 (包含0 和19) 之间的整数、纵坐标是0 到20 (包含0 和20) 之间的整数的点。
请问这些点一共确定了多少条不同的直线。

解题 思路:

确定一条直线的方式有很多种,但是我们知道,一个斜率和一个截距将会唯一确定一条直线,所以我们枚举所有的点,算出所有两点确定一条直线的斜率和截距,然后通过map函数去重,找到其中不一样的,横线和竖线很好算,这个单独考虑。

代码:

#include
using namespace std;
map,int> a;
struct point{
    double x;
    double y;
}point[1010];
int main()
{
    int ans=0;
    for(int i=0;i<20;i++)
    {
        for(int j=0;j<21;j++)
        {
            point[ans].x=i;
            point[ans].y=j;
            ans++;
        }
    }
    int sum=0;
    for(int i=0;i

E、路径

关于这种题目,我一般都不会写,当时数据结构这一章就没怎么听懂。

F、时间显示

题目描述

小蓝要和朋友合作开发一个时间显示的网站。
在服务器上,朋友已经获取了当前的时间,用一个整数表示。
值为从1970 年1 月1 日00:00:00 到当前时刻经过的毫秒数。
现在,小蓝要在客户端显示出这个时间。
小蓝不用显示出年月日,只需要显示出时分秒即可,毫秒也不用显示,直接舍去即可。
给定一个用整数表示的时间,请将这个时间对应的时分秒输出。

输入格式

输入第一行包含正整数T,表示存在T组测试数据,T不超过1000。
接下来T行,每行一个正整数表示时间。时间不超过10^18。

输出格式

输出T行,每行按照如下格式:
输出时分秒表示的当前时间,格式形如HH:MM:SS
其中HH 表示时,值为0 到23,MM 表示分,值为0 到59,SS 表示秒,值为0 到59。
时、分、秒不足两位时补前导0。

输入样例 复制

2
46800999
1618708103123

输出样例 复制

13:00:00
01:08:23

解题思路:

蓝桥杯是真的很喜欢考时间。这题没什么好说的,就是模拟吧。

代码:

#include
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        long long int ms;
        cin>>ms;
        long long int d=ms/3600000/24;
        long long int c=d*24*3600000;
        ms=ms-c;
        int h=ms/3600000;
        ms=ms-h*3600000;
        int m=ms/60000;
        ms=ms-m*60000;
        int s=ms/1000;
        int h1=0,m1=0,s1=0;
        if(h>=24)
        {
            h1=0;
        }
        else
        h1=h;
        if(m>=60)
        {
            m1=0;
        }
        else
        m1=m;
        if(s>=60)
        {
            s1=0;
        }
        else
        s1=s;
        printf("%02d:%02d:%02d\n",h1,m1,s1);
    }
    return 0;
}

G、砝码称重

题目描述

你有一架天平和N 个砝码,这N 个砝码重量依次是W1, W2, ... , WN。
请你计算一共可以称出多少种不同的重量?
注意砝码可以放在天平两边。

输入格式

输入的第一行包含一个整数N。
第二行包含N 个整数:W1, W2, W3, ... , WN。
对于50% 的评测用例,1 ≤ N ≤ 15。
对于所有评测用例,1 ≤ N ≤ 100,N 个砝码总重不超过100000。

输出格式

输出一个整数代表答案。

输入样例 复制

3
1 4 6

输出样例 复制

10

解题思路:

动态规划求解,dp[i][j]表示前i个砝码中能否称出j的重量,可以的话就是1,不可以的话就是0,其状态转移方程为:dp[i][j]=dp[i-1][j](第i个砝码不选)||dp[i-1][j+a[i]](第i个砝码选,并且加上之前的重量)||dp[i-1][abs(j-a[i])](第i个砝码选,并且减去之前的重量和,注意要使用abs,就算由重复的也没事,因为这里是或运算符,我们只是看是否能构成,存在即为1)。

代码:

#include
using namespace std;
int a[110];
bool dp[110][100010];
int main()
{
    int n;
    cin>>n;
    int sum=0;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        sum+=a[i];
    }
    dp[0][0]=true;
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=sum;j++)
        {
            dp[i][j]=dp[i-1][j]||dp[i-1][j+a[i]]||dp[i-1][abs(j-a[i])];
        }
    }
    int ans=0;
    for(int i=1;i<=sum;i++)
    {
        if(dp[n][i])
            ans++;
    }
    cout<

其实这题我还是会有一点疑惑就是会不会存在两个砝码的重量相同,那么称出来的重量是0的情况。

后面的几道题目中杨辉三角可以暴力通过部分数据,其他的还尚未解决。正在学习中…… 

 

 

 

 

 

你可能感兴趣的:(蓝桥杯,c++,算法)