第十二届蓝桥杯国赛C++B组 赛后总结

Posted mp-ui

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第十二届蓝桥杯国赛C++B组 赛后总结相关的知识,希望对你有一定的参考价值。

本人一本菜鸡,意外获得省一进入国赛,唯一的遗憾就是没能公费旅游,今年因为疫情改为线上比赛,所以只能去学校的实验室比赛了。。。下面是我做的一些答案希望大佬不要喷

A. 带宽

在这里插入图片描述
送分题,1Mbps = 1/8 MB/S,所以直接除以8,得到答案25

B. 纯质数

在这里插入图片描述
纯暴力,答案是1903
1一直暴力遍历到20210605太慢了,所以直接用DFS搜了。。

#include <bits/stdc++.h>
using namespace std;
int start = 1;
int _end = 20210605;

bool isZhi(int n){
    if(n <= 1){
        return 0;
    }
    for(int i = 2;i < n;++i){
        if(n % i == 0){
            return 0;
        }
    }
    return 1;
}

bool isChunZhi(int n){
    if(!isZhi(n)){
        return 0;
    }
    int j = n;
    while(j){
        int k = j % 10;
        if(!(k == 2 || k == 3 || k == 5 || k == 7)){
            return 0;
        }
        j /= 10;
    }
    return 1;
}

int cnt = 0;

void dfs(int n){
    if(n > _end){
        return;
    }
    if(isZhi(n)){
        ++cnt;
        cout << n << endl;
    }
    dfs(n * 10 + 2);
    dfs(n * 10 + 3);
    dfs(n * 10 + 5);
    dfs(n * 10 + 7);
}


int main(){
    dfs(0);
    cout << cnt << endl;
    return 0;
}

C. 完全日期

在这里插入图片描述
暴力遍历一趟,答案977

#include <bits/stdc++.h>
using namespace std;
int days[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
int days1[] = {0,31,29,31,30,31,30,31,31,30,31,30,31};

int year = 2001;
int month = 1;
int day = 1;

int ey = 2021;
int em = 12;
int ed = 31;

void nextDay(){
    // 是不是闰年
    if(year % 4 == 0){
        if(day < days1[month]){
            ++day;
        }else{
            day = 1;
            month++;
            if(month > 12){
                month = 1;
                ++year;
            }
        }
    }else{
        if(day < days[month]){
            ++day;
        }else{
            day = 1;
            month++;
            if(month > 12){
                month = 1;
                ++year;
            }
        }
    }
}

int main(){
    int cnt = 0;
    while(year < ey || (year == ey && (month < em) || (month == em && day <= ed))){
        cout << year << " " << month << " " << day << "    ";
        int sum = 0;
        int y = year;
        while(y){
            sum += y % 10;
            y /= 10;
        }
        int m = month;
        while(m){
            sum += m % 10;
            m /= 10;
        }
        int d = day;
        while(d){
            sum += d % 10;
            d /= 10;
        }
        cout << sum << "  ";
        double ss = sqrt(sum);
        cout << ss << "  ";
        if((int)ss == ss){
            ++cnt;
            cout << "是" << endl;
        }else{
            cout << "不是" << endl;
        }
        nextDay();
    }
    cout << cnt << endl;
    return 0;
}

D. 最小权值

在这里插入图片描述
这题没了,大佬们猜的都是完全二叉树,就我猜的是结点全部都在左边。。算出来的答案很大很大,不说了。。。。

E. 大写

在这里插入图片描述
送分题

#include <bits/stdc++.h>
using namespace std;
int main(){
    string s;
    cin >> s;
    for(int i = 0;i < s.length();++i){
        if(s[i] >= 'a' && s[i] <= 'z'){
            s[i] -= 32;
        }
    }
    cout << s << endl;
    return 0;
}

F. 123

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

分段+二分,想了好久我也不知道对不对

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll sum[1500000];

ll getn_np1(ll n){
    return n * (n + 1) / 2;
}

//二分
ll get(ll n){
    ll l = 1;
    ll r = 1500000;
    ll mid;
    while(l < r){
        mid = (l + r) >> 1;
        ll n_np1 = getn_np1(mid);
        if(n_np1 > n){
            r = mid;
        }else if(n_np1 < n){
            l = mid + 1;
        }else{
            return mid;
        }
    }
    return l;
}

void init(){
    int i = 1;
    ll summ = 0;
    while(i < 1500000){
        summ += i;
        sum[i++] = summ;
    }
}


int main(){
    init();
    int T;
    cin >> T;
    ll l,r;
    while(T--){
        cin >> l >> r;
        ll p = get(l); //第几段
        ll q = get(r); //第几段
        ll pp = p * (p - 1) / 2; //第几段前面有几个数
        ll ppp = l - pp; //段里面的第几个
        ll qq = q * (q - 1) / 2;//第几段前面有几个数
        ll qqq = r - qq; //段里面的第几个
        ll res = 0;
        if(p == q){
            res = qqq * (qqq + 1) / 2 - ppp * (ppp - 1) / 2;
        }else{
            res = sum[p] - ppp * (ppp - 1) / 2;
            res += qqq * (qqq + 1) / 2;
            for(int i = p+1;i <q;++i){
                res += sum[i];
            }
        }
        //cout << p << " " << pp << " " << ppp << "    " << q << " " << qq << " " << qqq << endl;
        cout << res << endl;
    }
    return 0;
}

G. 异或变换

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

一开始是暴力做的,快交卷了才发现这个竟然是周期的,临时改了改,应该能骗点分吧!

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
    ll n,t,tt;
    string s;
    string ss;
    cin >> n >> t;
    cin >> s;
    ss = s;
    tt = t;
    vector<string> v;
    v.push_back(s);
    while(t--){
        for(int i = 1;i < n;++i){
            ss[i] = ((s[i] - '0') ^ (s[i-1] - '0')) + '0';
        }
        s = ss;
        if(s == v[0]){
            ss = v[tt % v.size()];
            break;
        }
        v.push_back(s);
    }
    cout << ss << endl;
    return 0;
}

H. 二进制问题

在这里插入图片描述
大佬用数位DP(因为我不会),所以我只想到DFS,只要固定好1的个数就行了。应该能跑一半分,现场测试过,当N=2*1e9, K=30的时候很快可以出结果,但是当N=2*1e9, K=10的时候要跑几秒钟!

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int bits[64];
ll cnt = 0;

//d:多少个二进制位
ll bin_to_dec(int d){
    int i = 0;
    int j = d - 1;
    ll res = 0;
    while(j >= 0){
        if(bits[j] == 1){
           res += pow(2,i);
        }
        --j;
        ++i;
    }
    return res;
}


//i-当前索引,n-最大值,k-一共多少个一,d-最多多少位,one-用了多少个1
void dfs(int i,ll n,int k,int d,int one){
    if(one > k || one + d - i < k){
        return;
    }
    if(one + d - i == k || one == k || i == d){
        if(one + d - i == k){
            for(int j = i;j < d;++j){
                bits[j] = 1;
            }
        }
        if(bits[0] == 0){
            ++cnt;
        }else{
            if(bin_to_dec(d) <= n){
                ++cnt;
            }
        }
        /*
        for(int i = 0;i<d;++i){
            cout << bits[i];
        }
        cout << "->" << bin_to_dec(d) << endl;
        */
        if(one + d - i == k){
            for(int j = i;j < d;++j){
                bits[j] = 0;
            }
        }
        return;
    }
    bits[i] = 1;
    dfs(i+1,n,k,d,one+1);
    bits[i] = 0;
    dfs(i+1,n,k,d,one);
}

int main(){
    memset(bits,0,sizeof(bits));
    ll n,k;
    cin >> n >> k;
    //判断需要多少个二进制位
    double d = log(n) / log(2);
    d = ceil(d);
    dfs(0,n,k,d,0);
    cout << cnt << endl;
    return 0;
}

I. 翻转括号序列

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这题我没有任何想法,纯暴力骗分,好像看到大佬用的是树状数组还是线段树?

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
    ll n,m;
    cin >> n >> m;
    string s;
    cin >> s;
    int status;
    ll l,r;
    while(m--){
        cin >> status >> l;
        if(status == 1){
           //第一种操作
           cin >> r;
           for(int i = l - 1;i<=r - 1;++i){
               if(s[i] == '('){
                    s[i] = ')';
               }else{
                    s[i] = '(';
               }
           }
           //cout << s << endl;
        }else if(status == 2){
            //第二种操作
            int tag = 0;
            int i = l - 1;
            int ma = 0;
            while(i < s.length() && tag >= 0){
                if(s[i] == '('){
                    ++tag;
                }else{
                    --tag;
                }
                if(tag == 0){
                    ma = max(ma,i + 1);
                }
                if(tag < 0){
                    break;
                }
                ++i;
            }
            cout << ma << endl2021第十二届蓝桥杯国赛C/C++大学B组题解

2021第十二届蓝桥杯国赛C/C++大学B组题解

2021第十二届蓝桥杯国赛C/C++大学B组题解

2021第十二届蓝桥杯国赛C/C++大学B组题解

2021软件类第十二届蓝桥杯国赛真题 Python组 A-E题解

第十二届蓝桥杯国赛B组 做题记录(python)