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

    A. Puzzle From the

    题意:

    (a)(b) 两个数(长度相同)相加得到 (c),对于 (c) 中的如果某一段区间上的数字相同就省略只写一个(例如:(112200) 省略为:(120))就得到了 (d)。在已知 (b) 的情况下计算一个 (a) 要求使 (d) 最大。

    思路:

    显然对于一个数越长就越大,那么 (c) 的相邻位一定是不同的。第一位一定是 (2)

    代码:
    int main() {
    
        int t; cin >> t;
        while (t --) {
            int n;
            cin >> n;
            string a = "", b;
            cin >> b;
            int len_b = b.size();
            a += '1';
            for (int i = 1; i < len_b; i ++) {
                if (b[i] + '1' == a[i - 1] + b[i - 1]) a += '0';
                else a += '1';
            }
            cout << a << endl;
        }
        return 0;
    }
    

    B. Different Divisors

    题意:

    对于 (a) 的所有因数之差大于等于 (d)。求最小的满足条件的 (a)。((a) 至少有四个因数)

    思路:

    对于一个数来说至少有两个因数那就是 (1) 和他本身。

    那么我们从 (1) 开始,找一个 (ge d+1) 的素数 (x)。在找一个 (ge x+d) 的素数 (y)。那么 (x imes y) 就是答案。

    之所以找素数是因为如果我们找的是合数,那么对于这个合数还有其他因子,那么就无法判断。

    (x imes y) 根据质因数分解为:(x^1 imes y^1)。那么就只有这四个因数,显然 (a - y ge d) 的。所以合理。

    我们可以先预处理出素数,然后二分即可。

    代码:
    const int N = 1e7;
    vector<int> primes;
    int is_prime[N];
    
    void init() {
        memset(is_prime, 0, sizeof is_prime);
        for (int i = 2; i < N; i ++) {
            if (is_prime[i] == 0) primes.pb(i);
            int len_primes = primes.size();
            for (int j = 0; j < len_primes && primes[j] * i  < N; j ++) {
                is_prime[i * primes[j]] = 1;
                if (i % primes[j] == 0) break;
            }
        }
    }
    
    
    int main() {
    
        init();
        
        int len_primes = primes.size();
    
        int t; cin >> t;
        while (t --) {
            int d; cin >> d;
            int a = lower_bound(all(primes), d + 1) - primes.begin();
            int b = lower_bound(all(primes), primes[a] + d) - primes.begin();
            ll ans = 1ll * primes[a] * primes[b];
            cout << ans << endl;
        }
        return 0;
    }
    
    

    C. Array Destruction

    题意:

    给定一个数组 (a)。初始选定一个 (x),在数组中找两个数 (a, b) 满足 (a + b = x),那么 (a,b) 就从数组中删去,并且 (x = max(a, b)),继续操作下去,问是否可以把数组中的数删光?如果可以就输出初始的 (x) 和每次删除的 (a, b)

    思路:

    显然我们可以知道对于当前的操作下选取的 (a, b) 中的较大值一定是当前数组中的最大值,只有这样才有可能删完。那么根据当前的 (x),又从数组中选出当前的最大值,那么另一个数就可以求出来。只有第一次操作的时候,由于 (x) 的未知,所以无法确定另一个数。

    由于数组的长度 (le 2 imes 10^3)。那么我们可以暴力枚举第一次选取的另一个数。复杂度为 (O(n^2))

    代码:
    const int N = 2e3 + 10;
    map<int, int> mp;
    
    int a[N];
    vector<PII> ans;
    
    int main() {
    
        int t; cin >> t;
        while (t --) {
            mp.clear();
            int n; cin >> n;
            int flag = 0;
            int m = n << 1;
            for (int i = 1; i <= m; i ++) {
                cin >> a[i];
                mp[a[i]] ++;
            }
            sort(a + 1, a + m + 1);
            mp[a[m]] --;
            for (int i = 1; i < m; i ++) {
                ans.clear();
                ans.pb({a[m], a[i]});
                int j = m - 1;
                map<int, int> tmp_map = mp;
                tmp_map[a[i]] --;
                int pre = a[m];
                while (j > 0) {
                    if (tmp_map[a[j]]) {
                        if (pre - a[j] == a[j] && tmp_map[a[j]] >= 2) {
                            tmp_map[a[j]] -= 2;
                            ans.pb({a[j], a[j]});
                            pre = a[j];
                        } else if (pre - a[j] != a[j] && tmp_map[pre - a[j]]) {
                            tmp_map[a[j]] --;
                            tmp_map[pre - a[j]] --;
                            ans.pb({a[j], pre - a[j]});
                            pre = a[j];
                        } else {
                            break;
                        }
                    }
                    j --;
                }
                if (ans.size() == n) {
                    flag = 1;
                    break;
                }
            }
            if (flag) {
                puts("YES");
                cout << ans[0].x + ans[0].y << endl;
                for (int i = 0; i < n; i ++) cout << ans[i].x << " " << ans[i].y << endl;
            } else {
                puts("NO");
            }
        }
        
        return 0;
    }
    

    D. Cleaning

    题意:

    (n) 堆石头,每次你可以让相邻位上的石头数 (-1)(前提是有石头)。你有一次特殊操作是交换两堆相邻石头。问最终能否把石头的数量都变为 (0)

    思路:

    根据题意可知,第 (x) 堆石头只能由 (x+1) 堆来清除,直至第 (n) 堆清楚完第 (n-1) 堆后刚好为 (0)

    那么 (O(n^2)) 的做法就是枚举交换的位置,然后判断是否可行即可。

    此时我们可以发现在枚举交换位置后的判断有重复的计算,所以我们可以预处理出 (l)(r) 数组,(l[i]) 代表从左往右消除到位置 (i) 上剩余的石头数,(r[i]) 代表从右往左消除到位置 (i) 上的石头数量,如果 (l[i] = r[i + 1]) 就说明不用交换就可以消除完,那么我们枚举交换的位置 (i, i + 1),只需要判断四堆石头即:(l[i - 1], a[i], a[i + 1], r[i + 2]) 是否可以消除完即可。

    注:当 (l[i] < 0),那么之后的都是不合法的了。

    代码:
    const int N = 2e5 + 10;
    
    int a[N];
    ll l[N], r[N];
    
    int main() {
    
        int t; cin >> t;
        while (t --) {
            int n; cin >> n;
            memset(l, 0, sizeof l);
            memset(r, 0, sizeof r);
            int l_flag = n + 1, r_flag = -1;
            // LNF 为无穷大
            for (int i = 1; i <= n; i ++) {
                cin >> a[i];
                if (a[i] >= l[i - 1]) l[i] = a[i] - l[i - 1];
                else l[i] = LNF / 2;
            }   
            for (int i = n; i >= 1; i --) {
                if (a[i] >= r[i + 1]) r[i] = a[i] - r[i + 1];
                else r[i] = LNF;
            }
            int flag = 0;
            // 枚举交换的位置
            for (int i = 1; i <= n - 1; i ++) {
                if (l[i] == r[i + 1]) {
                    flag = 1;
                    break;
                }
                // 交换 i 和 i + 1
                if (a[i + 1] >= l[i - 1] && a[i] >= r[i + 2] && a[i + 1] - l[i - 1] == a[i] - r[i + 2]) {
                    flag = 1;   
                    break;
                }
            }
            if (flag == 1) puts("YES");
            else puts("NO");
        }
        return 0;
    }
    
  • 相关阅读:
    ubuntu 安装 redis desktop manager
    ubuntu 升级内核
    Ubuntu 内核升级,导致无法正常启动
    spring mvc 上传文件,但是接收到文件后发现文件变大,且文件打不开(multipartfile)
    angular5 open modal
    POJ 1426 Find the Multiple(二维DP)
    POJ 3093 Margritas
    POJ 3260 The Fewest Coins
    POJ 1837 Balance(二维DP)
    POJ 1337 A Lazy Worker
  • 原文地址:https://www.cnblogs.com/nonameless/p/14321699.html
Copyright © 2011-2022 走看看