Codeforces Round #696 (Div. 2) 个人题解

这篇博客介绍了三道编程竞赛题目,涉及贪心算法和欧拉筛法。第一题是寻找使得二进制数相加并合并后结果最大的策略;第二题通过欧拉筛法找出具有特定因子数量和差值限制的数;第三题探讨了删除数组元素的策略,要求每次删除的两个数之和等于前一次的最大数。文章通过实例解析了解题思路,并提供了C++代码实现。
摘要由CSDN通过智能技术生成

Codeforces Round #696 (Div. 2)

A. Puzzle From the Future

题意:给出一个二进制数b,要求另一个二进制数a使a + b再经过一定操作后的结果最大
(操作:结果中相邻单位的数字相同要合并为一个数);
思路:一道贪心题,首先明确位数多的始终比位数少的要大,a和b相加时能加1就加1,否则就加上0;

#include<bits/stdc++.h>
using namespace std;
 
const int maxn = 1e5 + 10;
int a[maxn], b[maxn], c[maxn];
 
int main() {
    int t; scanf("%d", &t);
    while(t--) {
        int len; scanf("%d", &len);
        for(int i = 0; i < len; i++) scanf("%1d", &b[i]);
        a[0] = 1; c[0] = a[0] + b[0];
        for(int i = 1; i < len; i++) {
            if(1 + b[i] == c[i - 1]) a[i] = 0;
            else a[i] = 1;
            c[i] = a[i] + b[i];
        }
        for(int i = 0; i < len; i++) 
            printf("%d", a[i]);
        puts("");
    }
    return 0;
}

B. Different Divisors
题意: 求出a, 要求a至少有4个因子且a的任意两个因子的差不小于d
思路:这种不太复杂的找规律题,直接打表观察

#include<bits/stdc++.h>
using namespace std;
 
const int maxn = 100000;
int prime[maxn], visit[maxn];
//欧拉筛法
void Prime() {
    for(int i = 2; i <= maxn; i++) {
        if(!visit[i]) prime[++prime[0]] = i;
        for(int j = 1; j <= prime[0] && prime[j] * i <= maxn; j++) {
            visit[prime[j] * i] = 1;
            if(i % prime[j] == 0) break;
        }
    }
}
 
int main() {
    Prime();
    int t; scanf("%d", &t);
    while(t--) {
        int d; scanf("%d", &d);
        int p = lower_bound(prime + 1, prime + prime[0] + 1, d + 1) - prime;
        p = prime[p];
        int q = lower_bound(prime + 1, prime + prime[0] + 1, p + d) - prime;
        q = prime[q];
        cout << p * q << endl;
    }
    return 0;
}

C. Array Destruction
题意:要删除一个数组所有的数,要求一次只能删除两个数,且两个数之和必须为上一次删除的两数中的最大值。
思路:因为这一次删除的数中的最大值为下一次两数的和,则必须要求删除的数中要包含当前数组中的最大值,否则该最大值将无法被删除。现在问题就是第一次删除时除最大数外的另外一个数如何选择,注意到n最大为1000,O(n^2)也是可以过的,枚举每一种情况就行了。

#include<bits/stdc++.h>
using namespace std;

const int maxn = 2 * 1000 + 10;

typedef pair<int, int> P;

void solve() {
    int arr[maxn];
    int n, mx = 0, pos; 
    scanf("%d", &n);
    n *= 2;
    for(int i = 0; i < n; i++) {
        scanf("%d", &arr[i]);
        if(arr[i] > mx) { mx = arr[i], pos = mx; }
    }
    for(int i = 0; i < n; i++) {                //枚举每种初始的x;
        if(i == pos) continue;    
        vector<P> res;
        multiset<int> ms;
        for(int i = 0; i < n; i++) ms.insert(arr[i]);
        int x = mx + arr[i], flag = 1;
        while(!ms.empty()) {
            int t = *ms.rbegin();
            ms.erase(ms.find(t));               //一定要先删除,否则当t == x - t 且 t 只出现一次时会出现问题;
            if(ms.find(x - t) == ms.end()) { 
                flag = 0; 
                break; 
            }
            else {
                ms.erase(ms.find(x - t));
                res.emplace_back(t, x - t);
                x = t;
            }
        }
        if(flag) {
            printf("YES\n%d\n", res[0].first + res[0].second);
            for(auto t : res) {
                printf("%d %d\n", t.first, t.second);
            }
            return ;
        }
    }
    printf("NO\n");
}

int main() {
    int t; scanf("%d", &t);
    while(t--) {
        solve();
    }
    return 0;
}

小总结:
1.emplace_back 和 push_back 有相同的作用,但前者效率要高很多。
2.mutiset就是可以有重复元素的set。

其它的待补

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值