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

lightmon發表於2024-06-07

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\)的答案是\(2^{25} = 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

發現\(x\)\(y\)的最長公共字尾對應的位可以從\(0\)開始連續地填,從\(00\)填到\(11\)就走完了這兩位可以提供的所有連續數值。如果從\(000\)填到\(111\)的話,因為更高位\(x\)\(y\)的值不同,所以異或出來的值不是連續的。

再看\(5432\)位,我們要保證\(x\)\(y\)都不能填\(0000\),因為\(0000\)會和後面兩位\(00\)組成\(0\),但是題目要求是從\(1\)開始。假設\(x\)\(0001\),如果\(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\)

\(x\)的總和為\(s\)

因為\(k_i * x_i > s\),所以\(x_i >= s / k_i + 1\),然後我們要保證所有的\(s / k_i + 1\)加起來小於等於\(s\)。因為這樣我們可以在每個\(s / k_i + 1\)上加若干值使得他們的總和等於\(s\),且仍然滿足\(k_i * x_i > 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';
}

相關文章