Codeforces Round #441 Div. 2 A B C D


題目鏈接

A. Trip for Meal

題意

三個點之間兩兩有路徑,分別長為\(a,b,c\),現在從第一個點出發,走\(n-1\)條邊,問總路徑最小值。

思路

記起始點相鄰的邊為\(a,b\),相對的邊為\(c\).

首先肯定走\(a,b\)中的最小值(不妨設為\(a\)),到達另一個頂點。那么這個頂點所連的兩條邊\(a,c\)中必然有一個是\(a,b,c\)三者中的最小值,否則最小值就為\(b\),與初始的選擇矛盾。

於是接下來只需要在最小值的路上反復走即可。

Code

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int main() {
    int n, a ,b,c;
    scanf("%d", &n);
    --n;
    scanf("%d%d%d", &a,&b,&c);
    if (n==0) { putchar('0'); exit(0); }
    if (b > a) swap(a,b);
    int ans = b;
    --n;
    if (b > c) ans += n*c;
    else ans += n*b;
    printf("%d\n", ans);
    return 0;
}

B. Divisibility of Differences

題意

\(n\)個數中取\(m\)個數關於\(\%k\)同余。

思路

統計\(\%k=0,1,...,k-1\)的數的個數。

Code

#include <bits/stdc++.h>
#define maxn 100010
using namespace std;
typedef long long LL;
int a[maxn], cnt[maxn], ans[maxn];
int main() {
    int n, m, k;
    scanf("%d%d%d", &n, &m, &k);
    for (int i = 0; i < n; ++i) {
        scanf("%d", &a[i]);
        ++cnt[a[i] % k];
    }
    for (int i = 0; i < k; ++i) {
        if (cnt[i] >= m) {
            printf("Yes\n");
            int tot = 0;
            for (int j = 0; j < n && tot < m; ++j) {
                if (a[j] % k == i) ans[tot++] = a[j];
            }
            printf("%d", ans[0]);
            for (int i = 1; i < tot; ++i) printf(" %d", ans[i]); printf("\n");
            exit(0);
        }
    }
    printf("No\n");
    return 0;
}

C. Classroom Watch

題意

給定一個數\(n(n\leq 1e9)\),已知\(n=x+(x各數位上數字之和)\),求所有滿足條件的\(x\).

思路

顯然,\(x\)最大只有\(9\)位,於是各數位上數字之和\(\leq 9*9=81\),循環\(81\)\(check\)即可。

Code

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int ans[100];
int digit(int x) {
    int ret = 0;
    while (x) {
        ret += x % 10;
        x /= 10;
    }
    return ret;
}
int main() {
    int n;
    scanf("%d", &n);
    int tot = 0;
    for (int i = max(n-81,0); i <= n; ++i) {
        if (i+digit(i) == n) ans[tot++] = i;
    }
    printf("%d\n", tot);
    for (int i = 0; i < tot; ++i) printf("%d\n", ans[i]);
    return 0;
}

D. Sorting the Coins

題意

給定一個全\(0\)的串,詢問\(n\)次,每次在上一次詢問的基礎上將串中某一個指定位置處的\(0\)變為\(1\),並問經過多少次操作能夠使整個串左邊全\(0\),右邊全\(1\).

一次操作:從左到右掃描,每遇到一個\(1\),如果它右邊是\(0\),就將它與右邊的\(0\)交換位置,再從下一個位置繼續開始掃描直至結束。

思路

首先,最右邊的若干個\(1\)是不用處理的;而對於其左邊所有的沒有與最右邊那塊連接起來的\(1\),效果上每次只能將其中一個(即最右邊的那個)移到與最右邊的若干個\(1\)合並。所以操作次數即為當前總的\(1\)的個數減去最右邊的連續的\(1\)的個數。

又因為最右邊的連續的\(1\)在整個過程中肯定是逐漸向左延伸的,故可以記錄左端點每次看是否可以向左拓展,時間復雜度\(O(n)\).

Code

#include <bits/stdc++.h>
#define maxn 300010
using namespace std;
typedef long long LL;
bool a[maxn];
int main() {
    int n;
    scanf("%d", &n);
    int l = n+1, r = n+1;
    putchar('1');
    for (int i = 1; i <= n; ++i) {
        int x;
        scanf("%d", &x);
        a[x] = 1;
        while (l > 1 && a[l-1]) --l;
        printf(" %d", i+1-(r-l));
    }
    putchar('\n');
    return 0;
}

小結

這樣的題目...有些遺憾晚上有課沒能打_(:з」∠)_

\(B\)\(C\)都很普通;
\(D\)很快想出了其中的道道但關於寫法還是繞了路,一開始是去記錄最右邊的沒有與最右邊的\(1\)連續的一塊然后各種討論后來發現不行;
\(A\)一上來還真被蒙住了_(:з」∠)_在討論是走兩條邊還是三條邊...好題好題.

說遺憾什么的...反正\(EF\)也不會做,\(ABCD\)又過了超級多_(:з」∠)_
不遺憾不遺憾。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM