2021蓝桥杯省赛b题解

本文介绍了多个编程竞赛题目,包括内存计算、卡片操作、直线表示、货物摆放、最短路径计算、时间显示、砝码称重、杨辉三角和双向排序等。通过这些题目,作者强调了编程竞赛在提升代码能力和解决实际问题中的作用,并提供了详细的解题思路和代码实现。
摘要由CSDN通过智能技术生成

​​​​​​近几年蓝桥杯再也不是暴力杯了,但是可以很好的锻炼自己的代码水平,可以以赛促学,不要老看代码,比赛后时写代码速度也很重要!

  1. 空间
  2. 在这里插入图片描述

 计组基础题:256MB=256 * 2^20 * 8 位
所以存放32位元素可以存放 256 * 1024 * 1024 * 8 / 32

2.卡片

在这里插入图片描述 

#include<iostream>

using namespace std;

const int maxn = 2021;

int  car[10];

int get(int x) {

    return x % 10;

}

int main(){

    for (int i = 0; i < 10; i++) {

        car[i] = maxn;

    }

    car[0]--;
    
    for (int k = 1;; k++) {

        int i = k;

        while (i) {

            int x=get(i);

            car[x]--;

            if (car[x] == -1) {

                cout << k-1 << endl;//因为这个数字已经不能拼了

            }

            i /= 10;

        }

    }

return 0;

}

3.直线

在这里插入图片描述

 

#include<iostream>

#include<set>

using namespace std;

set<pair<double, double>>line;

double ins = 1e-5;

int main() {

    double  x1, y1, x2, y2;

    for (x1 = 0; x1 < 20; x1++) {

        for (y1 = 0; y1 < 21; y1++) {
    
            for (x2 = 0; x2 < 20; x2++) {

                for (y2 = 0; y2 < 21; y2++) {

                    if (x1 != x2 && y1 != y2) {

                        double k = (y2 - y1) / (x2 - x1);

//double b = y2 - k * x2;如果按照第一种写法,

//那么y2是int型的,int减double会精度缺失,

//像第二种解法,同分了就比较高精度。

                        double b = (y2 * (x2 - x1) - (y2 - y1) * x2) / (x2 - x1);

                        pair<double, double> newline;

                        newline.first = k;

                        newline.second = b;

                        line.insert(newline);
    
                    }

                }

            }

        }

    }

    printf("%d", line.size() + 20 + 21);

    return 0;

}

4.货物摆放

在这里插入图片描述

 

//求这个数的约数用约数排列组合

//因为只有是约数才有可能乘机是这个数

#include<iostream>

using namespace std;

typedef long long LL;

LL n = 2021041820210418;

LL mun[101000], cnt=0;

int main() {

    for (LL i = 1; i <= n/i; i++) {

        if (n % i == 0) {

            mun[++cnt] = i;

                if (i * i != n) {
    
                    mun[++cnt] = n / i;

                }

        }

    }

    cout << cnt << endl;

    int ans = 0;
    
    for (int i = 1; i <= cnt; i++) {

        for (int j = 1; j <= cnt; j++) {

            if (n % (mun[i] * mun[j]) == 0) {

                ans++;

            }

        }

    }

    cout << ans << endl;



    return 0;

}

5.路径

在这里插入图片描述

#include<iostream>

using namespace std;

int mp[2022][2022];

const int inf = 0x3f3f3f3f;



int d[2022];//大一点

bool vis[2022];





int gcd(int a, int b) {

    return b ? gcd(b, a % b) : a;

}

int main() {

    for (int i = 1; i <= 2021; i++) {

        for (int j = 1; j <= 2021; j++) {

            if (i == j) {

                mp[i][j] = 0;

            }

            else if (abs(i - j) > 21) {

                mp[i][j] = mp[j][i] = inf;

            }

            else {

                mp[i][j] = mp[j][i] = i * j / gcd(i, j);

            }

        }

    }

//floyd

/*for (int i = 1; i <= 2021; i++) {

    for (int j = i+1; j <= 2021; j++) {

        for (int k = i; k <= j; k++) {

            mp[i][j] = min(mp[i][j], mp[i][k] + mp[k][j]);

        }

    }

}*/

//dijkstra

    memset(vis, false, sizeof(vis));

    memset(d, 0x3f3f3f3f, sizeof(d));

    d[1] = 0;

    for (int i = 1; i <= 2021; i++) {

        int x = 0;

        for (int j = 1; j <= 2021; j++) {
        
            if (!vis[j]&&d[j]<d[x]) {

                x = j;

            }

        }

        vis[x] = true;

        for (int j = max(1, x - 21);j <= min(2021, x + 21); j++) {//剪枝只有这些边有值才会有边
    
            d[j] = min(d[j], d[x] + mp[x][j]);

        }

    }

    //cout << mp[1][2021] << endl;

    cout << d[2021] << endl;

    return 0;

}

6.时间显示

在这里插入图片描述

 在这里插入图片描述

 

#include<iostream>

using namespace std;

int main(){

    long long time,s;

    int h, m;

    cin >> time;

    s = time / 1000;

    h = s / 3600 % 24;

    s = s % 3600;

    m = s / 60 ;

    s = s % 60;

    printf("%02d:%02d:%02ld", h, m, s);

    return 0;

}

7.砝码称重

在这里插入图片描述

 在这里插入图片描述

 

#include<iostream>

using namespace std;

const int N = 110,M=100010;

int a[N],m;

bool dp[N][M];

int main() {

    int n;

    cin >> n;

    for (int i = 1; i <= n; i++) {

        cin >> a[i];
        
        m += a[i];

    }

    dp[0][0] = true;

    for (int i = 1; i <= n; i++) {

        for (int j = 0; j <= m; 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 <= m; i++) {

        if (dp[n][i]) {

            ans++;

        }

    }

    cout << ans << endl;

    return 0;

}

8.杨辉三角

在这里插入图片描述

在这里插入图片描述 

 

#include<iostream>

using namespace std;

int a[2005][2005];

int main() {

    //二项式问题

    //二项式定理,对于C(3,n),当n等于2000时,C(3,2000)>1e9
    
    //因此只需要算到第2000行就好了,剩下的再算C(1,n)和C(2,n)就好了。

    int n;

    cin >> n;

    memset(a, 0, sizeof(a));

    a[0][0]=1;

    for (int i = 1; i <= 2005; i++) {

        for (int j = 1; j <= i; j++) {

            a[i][j] = a[i - 1][j] + a[i - 1][j - 1];

            if (a[i][j] == n) {

                cout << i * (i - 1) / 2 + j << endl;

                return 0;

            }

        }

    }

    int a;

    a = sqrt(n * 2) + 1;//杨辉三角和二项式的关系

    if (a * (a - 1) / 2 == n) {//c(2 ,n)c是排列a是组合

        cout << a * (a - 1) / 2 + 3 << endl;

    }

    else {

        cout << n * (n - 1) / 2 + 2 << endl;

    }

return 0;

}

9.双向排序(部分分值)

在这里插入图片描述

在这里插入图片描述 

 

#include<iostream>

#include<algorithm>

using namespace std;

int a[100010];

bool cmp(int a, int b) {

    return a > b;

}

int main() {

    int n, m;

    cin >> n >> m;

    for (int i = 1; i <= n; i++)a[i] = i;

    while (m--) {

        int p, q;

        cin >> p >> q;

        if (p == 0) {

            //sort(a + 1, a + q + 1, greater<int>());

            sort(a + 1, a + q + 1, cmp);

        }else{

            sort(a + q, a + 1 + n);



        }

    }

    for (int i = 1; i <= n; i++) {

        cout << a[i] << " ";

    }

    cout << endl;

    return 0;

}

10.括号序列

在这里插入图片描述

 

错误

思路在右括号多时从右边开始反过来

#include<iostream>

#include<string>

using namespace std;

int ans=0;

int x = 0;//第几个符号

int lm=0, rm=0,mun,vis;

string s;

void bfs(int x,int l,int r) {

    if (x == s.size()) {

        if (l == r)ans++;

        cout << l << " " << r<<endl;

        return;

    }

    char c=s[x];

    if (c == '(') {

        l++;

    }

    else {

        r++;

    }

    cout <<" "<< l << " " << r << endl;



    for (int i = abs(l - r); i >= 0; i--) {

        if (vis) {

            if (i)vis -= i;

            if (mun) {

                bfs(x + 1, r + i, l);

            }

            else {

                bfs(x + 1, l, r + i);

            }

        if (i)vis += i;

        }

        else  if (i == 0) {

            bfs(x + 1, l, r);

        }

    }

    if (c == '(') {

        l--;

    }

    else {

        r--;

    }

    return;

}

int main() {

    cin >> s;

    for (int i = 0; i < s.size(); i++) {

        if (s[i] == '(')lm++;
    
        if (s[i] == ')')rm++;

    }

    mun = rm - lm;

    vis = abs(rm - lm);

    cout << mun << endl;

    bfs(0,0,0);

    cout << ans<<endl;

    return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值