codeforces round 961题解(A、B、C)

A. Guess the Maximum

因为i<j,所以所有的[i,j]区间中都至少包含两个相邻元素,所以只要求出所有相邻元素中较大值的最小值即可。

int n;
int a[N];

void solve() {
    cin >> n;
    int min_v = 1e9 + 1;
    for (int i = 1; i <= n; i ++) {
        cin >> a[i];
    }
    for (int i = 1; i <= n - 1; i ++) {
        min_v = min(min_v, max(a[i], a[i + 1]));
    }
    cout << min_v - 1 << '\n';
}

B. XOR Sequences

观察结论,发现样例4的答案是225=33554432,猜测所有答案都是2的次方。

以样例3为例:

    5432 10        5432 10
57: 1110 01    37: 1001 01
    0100 00        0011 00
    0100 01        0011 01
    0100 10        0011 10
    0100 11        0011 11

发现xy的最长公共后缀对应的位可以从0开始连续地填,从00填到11就走完了这两位可以提供的所有连续数值。如果从000填到111的话,因为更高位xy的值不同,所以异或出来的值不是连续的。

再看5432位,我们要保证xy都不能填0000,因为0000会和后面两位00组成0,但是题目要求是从1开始。假设x0001,如果y必须填0000才能保证前缀异或相同,那么我们可以把x改填0011,因为异或的性质,原本第3位取的是x的第三位,现在我们改成1,就是取x的第三位取反,那么y的第三位就也必须取反,那么y就得填0010。这样,我们总可以不用选0000去填。

int x, y;

void solve() {
    cin >> x >> y;
    int i;
    for (i = 0; i <= 30; i ++) {
        if ((x >> i & 1) != (y >> i & 1)) {
            cout << (1 << i) << '\n';
            return;
        }
    }
    cout << (1 << i) << '\n';
}

C. Earning on Bets

吐槽:忘了删刚开始猜的判断1的情况,导致赛时一直WA 8

更新:刚开始猜的是对的,在判断flag==1时应该这样写:

flag > 1 && fabs(flag - 1) < 1e-6

x的总和为s

因为kixi>s,所以xi>=s/ki+1,然后我们要保证所有的s/ki+1加起来小于等于s。因为这样我们可以在每个s/ki+1上加若干值使得他们的总和等于s,且仍然满足kixi>s

那么我们可以二分查找这个s,找不到就输出1

int n;
int k[55];
int a[55];

bool check(int x) {
    int sum = x ;
    for (int i = 1; i <= n; i ++) {
        sum -= x / k[i];
    }
    return sum >= n;
}

void solve() {
    cin >> n;
    for (int i = 1; i <= n; i ++) {
        cin >> k[i];
    }
//    double flag = 0;
//    for (int i = 1; i <= n; i ++) {
//        flag += (double)1 / (double)k[i];
//    }
//    if (flag > 1 || fabs(flag - 1) < 1e-6) {
//        cout << -1 << '\n';
//        return;
//    }
    int l = n - 1, r = n * (int)1e9 + 1;
    while (l < r) {
        int mid = l + r >> 1;
        if (check(mid)) r = mid;
        else l = mid + 1;
    }
    int s = l;
    if (s == n - 1 || s == n * (int)1e9 + 1) {
        cout << -1 << '\n';
        return;
    }
//    cout << l << '\n';
    int sum = 0;
    for (int i = 1; i <= n; i ++) {
        a[i] = s / k[i] + 1;
        sum += a[i];
    }
    int cnt = l - sum;
    a[1] += cnt;
    for (int i = 1; i <= n; i ++) {
        cout << a[i] << ' ';
    }
    cout << '\n';
//    sum = 0;
//    for (int i = 1; i <= n; i ++) {
//        sum += a[i];
//    }
//    for (int i = 1; i <= n; i ++) {
//        cout << a[i] * k[i] - sum << ' ';
//    }
//    cout << '\n';
}
posted @   lightmon  阅读(41)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示