zoukankan      html  css  js  c++  java
  • 2021.6.5 蓝桥杯国赛B组

    A.带宽

    没啥好说的8b = 1B,所以直接200 / 8 = 25即可

    大家应该都对的吧(除了我可怜的涛酱

    B.纯质数

    纯打表题。我的答案:1903

    附上打表程序。

    #include <bits/stdc++.h>
    using namespace std;
    int dic[8] = {2,3,5,7};
    
    bool check(int x) {
        while (x) {
            int a = x % 10;
            int flag = 0;
            for (int i = 0; i < 4; i ++) {
                if (a == dic[i]) {
                    flag = 1;
                }
            }
            if (flag == 0) return 0;
            x /= 10;
        }
        return 1;
    }
    
    int main() {
        int ans = 0;
        for (int i = 2; i <= 20210605; ++ i) {
                int flag = 0;
            for (int j = 2; j *j <= i; ++ j) {
                if (i % j == 0) {
                    flag = 1;
                    break;
                }
            }
        if (flag == 0 && check(i)) ans ++;
        }
        cout << ans << endl;
        return 0;
    }

    C.完全日期

    简单模拟。我的答案:983 ------UPD:忘记判二月了,答案为977

    附上程序:

    #include <bits/stdc++.h>
    using namespace std;
    int dbound[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    
    int isrun(int year) {
        return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
    }
    
    int getsum(int x) {
        int sum = 0;
        while (x) {
            sum += x % 10;
            x /= 10;
        }
        return sum;
    }
    
    bool check(int year, int month, int day) {
        int sum = 0;
        sum += getsum(year);
        sum += getsum(month);
        sum += getsum(day);
        int base = sqrt(sum);
        return base * base == sum;
    }
    
    int main() {
        int year = 2001, month = 1, day = 1;
        int ans = 0;
        while (1) {
            if (check(year, month, day)) {
                ans ++;
                cout << year << " " << month << " " << day << endl;
            }
            if (year == 2021 && month == 12 && day == 31) {
                break;
            }
            day ++;
            if (day > dbound[month] + isrun(year)) { ///这里忘记判二月了。摆烂
                month ++;
                day = 1;
            }
            if (month > 12) {
                year ++;
                month = 1;
            }
        }
        cout << ans << endl;
        return 0;
    }

    D. 最小权值

    www这道题是个DP赛中看出来了。但是碍于DP水平有限(其实就是没有),被卡了很久。直到最后也没写出来。

    怎么身边的人都秒掉了www真的该好好学学dp了。

    (没做出来之后补)

    E.大写

    没啥好说的。

    #include <bits/stdc++.h>
    using namespace std;
    char s[105];
    
    int main() {
        scanf("%s", s);
        int n = strlen(s);
        for (int i = 0; i < n; ++ i) {
            if (s[i] <= 'z' && s[i] >= 'a')
                s[i] = s[i] - 'a' + 'A';
        }
        cout << s << endl;
        return 0;
    }

    F.123

    这道题较为简单。首先二分求出所求数字在哪一个块里。之后通过暴力求出之前的块的和是多少。之后再前缀和求出当前块的是多少即可。

    UPD:这个想法似乎是错的。问题就出在暴力跑出之前块的和是多少这一步。n的范围是1-1e12开根号之后就是1e6之后T又是1e6那么这个做法会被卡到1e12的复杂度。直接见祖宗。

    跟队友交流了一番他们说是二维前缀和来优化这一步操作。www之后再想想吧

    附上代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    ll get(ll x) {
        ll L = 1, R = 1e6;
        ll ans = 0;
        while (L <= R) {
            ll mid = L + R >> 1;
            if (mid * (mid + 1) / 2 <= x) {
                L = mid + 1;
                ans = max(ans, mid);
            }
            else {
                R = mid - 1;
            }
        }
        ll sum = 0;
        for (int i = 1; i <= ans; ++ i) {
            sum += 1ll * i * (ans - i + 1);
        }
        ll res = x - ans * (ans + 1) / 2;
        sum += res * (res + 1) / 2;
    //    cout << ans << " " << sum << endl;
        return sum;
    }
    
    int main() {
        int T; scanf("%d", &T);
        while (T--) {
            ll l, r; scanf("%lld%lld", &l, &r);
            printf("%lld
    ", get(r) - get(l-1));
        }
        return 0;
    }

    G.异或变换

    当时猜了个结论觉得循环节不是很大所以这做这道题的关键就是找循环节。

    各种STL代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 10000+10;
    int n;
    ll t;
    char s[maxn];
    bitset<maxn> bt;
    unordered_map<bitset<maxn>, int> mp;
    vector<bitset<maxn> > rec;
    
    void out(bitset<maxn> b) {
        for (int i = 0; i < n; i++)
            cout << b[i];
        cout << endl;
    }
    int main() {
        scanf("%d%lld", &n, &t);
        scanf("%s", s);
        for (int i = 0; i < n; ++ i) {
            bt[i] = (s[i] == '1');
        }
    //    out(bt);
        rec.push_back(bt);
        mp[bt] = 0;
        ll st = t, len = 1;
        for (int i = 1; i <= t; ++ i) {
            bitset<maxn> temp;
            temp[0] = bt[0];
            for (int j = 1; j < n; ++ j) {
                temp[j] = (bt[j] != bt[j-1]);
            }
            swap(bt, temp);
    //        out(bt);
            if (mp.count(bt)) {
                st = mp[bt];
                len = i - st + 1;
                break;
            }
            mp[bt] = i;
            rec.push_back(bt);
        }
    //    cout << st << " " << len << endl;
    //    cout << st + t % len <<endl;
        out(rec[st + t % len]);
        return 0;
    }

    H.二进制问题

    非常典型的数位dp问题。直接组合数算贡献也是可以做的。但是很遗憾的是我是数位dp板子型选手。无奈只能敲了暴力。

    艹写题解的时候发现暴力敲错了。去世了。似乎把算二进制最高位算成十进制最高位了。直接升天。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 10000+10;
    ll n;
    int k;
    ll pw2[65];
    int lmt = 0;
    ll ans = 0;
    void DFS(ll sum, int cnt, int wei) {
    //    cout << sum << " " << cnt << " " << wei << endl;
        if (sum > n) return ;
        if (cnt > k) return ;
        if (wei > lmt) {
            if (cnt == k) {
    //            cout << sum << endl;
                ans ++;
            }
            return ;
        }
    
        DFS(sum + pw2[wei], cnt + 1, wei + 1);
        DFS(sum, cnt, wei + 1);
    }
    
    int main() {
        scanf("%lld%d", &n, &k);
        pw2[0] = 1;
        for (int i = 1; i <= 62; ++ i) {
            pw2[i] = pw2[i-1] * 2;
    //        cout << pw2[i] << endl;
        }
        ll tn = n;
        while (tn) {
            tn /= 2; ///这里写成了10
            lmt ++;
        }
        lmt ++;
        DFS(0, 0, 0);
        printf("%lld
    ", ans);
       // cout << lmt << endl;;
        return 0;
    }

    I.翻转括号序列

    写了份暴力。复杂度是n * m。用bitset优化了翻转过程

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 1000000+10;
    int n, m;
    
    bitset<maxn> bt;
    char s[maxn];
    int _find(int st) {
        int flag = 0;
        int ans = 0;
        for (int i = st; i <= n; ++ i) {
            if (bt[i] == 1) {
                flag ++;
            }
            else {
                flag --;
                if (flag < 0) {
                    return ans ;
                }
                if (flag == 0) ans = i;
            }
        }
        return ans;
    }
    vector<bitset<maxn> > Lbt;
    vector<bitset<maxn> > Rbt;
    /*
    7 5
    ((())()
     */
    
    void out(bitset<maxn> b) {
        for (int i = 1; i <= n; ++ i)
            cout << b[i];
        cout << endl;
    }
    
    int main() {
        scanf("%d%d", &n, &m);
        scanf("%s", s+1);
        bitset<maxn> b2, b1;
        for (int i = 1; i <= n; ++ i) {
            b2[i] = 1;
        }
        Lbt.push_back(b1);
        Rbt.push_back(b2);
    
        for (int i = 1; i <= n; ++ i) {
            bt[i] = (s[i] == '(');
            b1[i] = 1;
            Lbt.push_back(b1);
            Rbt.push_back(b1^b2);
        }
        for (int i = 1; i <= m; ++ i) {
            int oper;
            scanf("%d", &oper);
    //        out(bt);
            if (oper == 1) {
                int l, r; scanf("%d%d", &l, &r);
                bt = bt ^ Rbt[0] ^ Lbt[l-1] ^ Rbt[r];
    //            out(Rbt[0]);
    //            out(Lbt[l-1]);
    //            out(Rbt[r]);
    //            out(bt);
            }
            else {
                int l; scanf("%d", &l);
                printf("%d
    ", _find(l));
            }
        }
        return 0;
    }

    J.异或三角形

    看了下应该是算贡献一类的题目。但是没啥时间就写了发n2的暴力

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 10000+10;
    
    bool check(int x, int y, int k) {
        if (x + y > k && x + k > y && y + k > x) return 1;
        return 0;
    }
    
    int main() {
        int T; scanf("%d", &T);
        while (T--) {
            int n; scanf("%d", &n);
            int ans = 0;
    //        for (int n = 1; n <= 100; ++ n) {
                for (int i = 1; i <= n; ++ i) {
                        for (int j = i+1; j <= n; ++ j) {
                            int k = i ^ j;
                            if (k > j && check(i, j, k)) {
                                ans ++;
    //                                cout << i << " " << j << " " << k << endl;
                            }
                        }
    
                }
    //            cout << ans << endl;
                printf("%d
    ", ans * 6);
    //        }
        }
        return 0;
    }

    --------------------------------------------------

    www我还以为这次应该打挺好的。但是写题解的时候发现其实错了很多。

    虽然个人感觉比我第一次打省赛要简单,但是其实分数可能还没有第一次省赛好。好难受。估计要没好一点的国奖了。

    希望明天出分数的时候能不太难受吧。

    -------------------------------------------------------

    UPD6.8: 喜提优胜奖

  • 相关阅读:
    Linux:修改Shell命令提示符及颜色
    Linux:cut命令详解
    pageadmin去掉xxx
    高手详解SQL性能优化十条经验
    一道简单递归题
    list<?>转换成 对应的 class
    《一道笔试题》找出最连续数字的最大长度
    poi 获取excel数据 导入数据库
    有一个5ml 的瓶子 和3ml 的瓶子 和 很多水 现在 要取出4ml的水 请写出编程 多种解法
    假设字符串类似这样的aba和aab,abc和bca就相等,现在随便给你二组字符串,请编程比较他们看是否相等
  • 原文地址:https://www.cnblogs.com/Vikyanite/p/14852707.html
Copyright © 2011-2022 走看看