zoukankan      html  css  js  c++  java
  • Codeforces Round #696 (Div. 2) (A~C题解)

    写在前边

    链接:Codeforces Round #696 (Div. 2)

    A. Puzzle From the Future

    链接:A题链接

    题目大意:

    给定一个(a),(b)(d = a + b),例如:(a = 0101), (b= 1111), (d = 1212),但是d如果有连续重复的数字那么会省掉,假如(a + b = 12211),则(d = 121),现在已知(a)(b)丢失了,要求求出一个(b)使得(d)最大。

    思路

    首先要使得(d)最大化,(b)的第一位必定是(1),剩下的直接从前到后模拟即可,若(a_i + b_i == d[i-1])那么(d)会减小,因此“反其道而行之即可”。

    代码:

    #include <iostream>
    #include <string>
    #include <algorithm>
    #include <cstdio>
    
    using namespace std;
    
    #define Inf 0x3f3f3f3f
    #define PII pair<int, int>
    #define PLL pair<long, long>
    
    typedef long long LL;
    typedef unsigned long long ULL;
    
    void solve() {
        string s, res = "1";
        int n;
        cin >> n;
        cin >> s;
        for (int i = 1; i < s.size(); i++) {
            if (((s[i]-'0') + 1) == (s[i - 1] - '0' + res[i - 1] - '0')) {
                res += '0';
            } else {
                res += '1';
            }
        }
    
        cout << res << endl;
    }
    
    int main()
    {
        int t;
        cin >> t;
        while (t--) {
            solve();
        }
    
        return 0;
    } 
    

    B. Different Divisors

    链接:B题链接

    题目大意:

    给定一个(d),求(a),要求(a)至少有(4)个约数,并且约数两两之间的至少差(d),并且要求(a)是可行方案中中的最小值。

    思路

    (quad) 题目要求四个约数,那么让其只有四个约数即可,即(1 quad p quad q quad pq)(p >= 1 + d), (q >= p + d),因此(p)就是大于(d + 1)的最小质数,(q)就是大于(p + d)的最小质数,那么(p * q)就是满足条件(a)
    证明:
    (quad)(p)是一个(>=1+d)合数,那么(1 -- p)之间必定还会会有一个(p)的约数(p′),因为(p′)(p)的约数,那么它必然也是(a)的约数这就使得(p′-1 < d),不满足约数之间至少差(d)的条件,因此矛盾。
    (quad)(p)不是最小质数,设其为(p′),另一个为(q′),那么(p′ * q′ > p*q),因此(p′)(q′)并不是最优解。

    综上(p)(p >= 1 + d)的最小质数与(q)(q >= p + d)最小质数为最优解。

    代码:

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <vector>
    
    using namespace std;
    
    #define Inf 0x3f3f3f3f
    #define PII pair<int, int>
    #define PLL pair<long, long>
    
    typedef long long LL;
    typedef unsigned long long ULL;
    typedef vector<long long> VLL;
    typedef vector<int> VI;
    
    const int N = 25e3 + 10;
    int primes[N], cnt;
    bool st[N];
    
    void get_primes() {
        for (int i = 2; i <= N; i++) {
            if (!st[i]) {
                primes[cnt++] = i;
            }
            for (int j = 0; primes[j] <= N / i; j++) {
                st[primes[j] * i] = true;
                if (i % primes[j] == 0) {
                    break;
                }
            }
        }
    }
    
    void solve() {
        int d;
        cin >> d;
        int p, q, pcnt = 0;
        for (pcnt; pcnt <= cnt; pcnt++) {
            if (primes[pcnt] - 1 >= d) {
                p = primes[pcnt];
                break;
            }
        }
        for (int i = pcnt; i <= cnt; i++) {
            if (primes[i] - p >= d) {
                q = primes[i];
                break;
            }
        }
        cout << p * q << endl;
    }
    
    int main()
    {
        int t;
        cin >> t;
        get_primes();
        while (t--) {
            solve();
        }
       
        return 0;
    } 
    

    C. Array Destruction

    链接:C题链接

    题目大意:

    例如,如果最初(a=[3,5,1,2]),则可以选择(x=6)。然后你可以选择第二个和第三个元素的总和(5+1=6),并抛出它们。在这个运算之后,(x)等于(5),数组中有两个元素:(3)(2)。你可以在下次操作时把它们扔了,那么输出

    YES
    6
    1 5
    2 3
    

    若无论如何数组内元素都无法清空,那么输出(NO)即可。

    思路

    每次选最大的数作为x。
    证明:
    假设(a_i < a_j < a_k),不选(a_j)来构造x,那么即(a_i + a_j = x),此后(x = a_j),之后无论如何都消除不掉(a_k),因此每次选最大数作为x即可。

    那么第一次除了选最大的数作为下一轮的x,另一个数就需要枚举所有可能,直到枚举到一个可以消掉所有数的情况。明白了这一点那么剩下的只需要模拟即可,可以用(multiset),因为其查找删除插入操作都是(O(logn)),若不用(multiset)则手写二分查找即可,最时间复杂度:(O(n^2logn))

    自己的错误:写了一晚上,但最后还是(TLE2)告终,其实我已经知道了每次要选最大值了,但还是用双指针来搜哪两个数等于(x),由于答案唯一,因此搜的结果是对的,但是导致(O(n^3))被卡,应该直接确定数组中还剩下的最大数,然后剩下的小数直接用二分搜就好了。

    代码:

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <vector>
    #include <set>
    
    using namespace std;
    
    #define Inf 0x3f3f3f3f
    #define PII pair<int, int>
    #define PLL pair<long, long>
    
    typedef long long LL;
    typedef unsigned long long ULL;
    typedef vector<long long> VLL;
    typedef vector<int> VI;
    
    vector<PII> check(VI all, int n, int x) {
        vector<PII> res;
        multiset<int> s;
        for (auto it : all) {
            s.insert(it);
        }
        for (int i = 0; i < n; i++) { //2*n个数,n个答案
            auto it1 = s.end();
            it1--;
            int y = x - *it1;
            s.erase(it1);
            auto it2 = s.find(y);
            if (it2 == s.end()) {
                return {};
            }
            s.erase(it2);
            res.push_back({y, x - y});
            x = max(x - y, y);
        }
        return res;
    }
    
    void solve() {
        int n;
        cin >> n;
        VI all;
        for (int i = 0; i < n * 2; i++) {
            int c;
            cin >> c;
            all.push_back(c);
        }
        sort(all.begin(), all.end());
        for (int i = 0; i < all.size() - 1; i++) { //枚举第一次操作的第二个数
            int x = all[i] + all[all.size() - 1]; //最大的一个
            vector<PII> res = check(all, n, x);
    
            if (res.size()) {
                cout << "YES" << endl;
                cout << x << endl;
                for (auto it : res) {  
                    cout << it.first << " " << it.second << endl; 
                }
                return;
            }
        }
        cout << "NO" << endl;
    }
    
    int main()
    {
        int t;
        cin >> t;
        while (t--) {
            solve();
        }
    
        return 0;
    } 
     
    
    
  • 相关阅读:
    编程自学网站
    SQL中Case语句用法
    SQL 综合应用(1.创建临时表,为后续查询所用) 实例_(学生,课程表,选修表)
    SQL 存储过程(学生,课程表,选修表)
    测试角度看公司流程规范对比后篇
    自动化测试技巧之图片验证
    QTP连载四:神一样的参数化方式?
    自动化测试之控件点击
    自动化测试技巧之结果验证
    自动化测试开展的条件
  • 原文地址:https://www.cnblogs.com/ZhengLijie/p/14307468.html
Copyright © 2011-2022 走看看