Codeforces Round #638

A

可知把最大的分配給a,從大到小分配n/2個元素給b,其餘給a

int t; cin >> t;
while (t--)
{
    int n; cin >> n;
    ll ans1 = 0, ans2 = 0;
    ans1 = 1 << n;
    for (int i = n - 1; i >= n - n / 2; --i) {
        ans2 += 1 << i;
    }
    for (int i = n - n / 2 - 1; i >= 1; --i) {
        ans1 += 1 << i;
    }
    cout << ans1 - ans2 << endl;
}

B

構成循環節,分析可得出現數字種類多於k將無法構造
按照出現的數字,在原序列中補充即可

int a[maxn], vis[105];
vector<int> ans, pre;
int main()
{
    int t; scanf("%d", &t);
    while (t--) {
        int n, k; scanf("%d%d", &n, &k);
        memset(vis, 0, sizeof(vis)); pre.clear();
        for (int i = 1; i <= n; ++i) {
            scanf("%d", &a[i]);
            if (vis[a[i]]++ == 0) {
                pre.push_back(a[i]);
            }
        }
        if (pre.size() > k) {
            printf("-1\n");
            continue;
        }
        if (n == 1) {
            printf("1\n1\n");
            continue;
        }
        while (pre.size() < k) pre.push_back(1);
        sort(pre.begin(), pre.end());
        ans.clear();
        for (int i = 1, last; i <= n; ++i) {
            if (i == 1) {
                for (int j = 0; j < k; ++j) {
                    ans.push_back(pre[j]);
                    if (pre[j] == a[i]) {
                        last = j + 1;
                        break;
                    }
                }
            }
            else if (i != n) {
                for (int j = last; j < k; ++j) {
                    ans.push_back(pre[j]);
                }
                for (int j = 0; j < k; ++j) {
                    ans.push_back(pre[j]);
                    if (pre[j] == a[i]) {
                        last = j + 1;
                        break;
                    }
                }
            }
            else {
                for (int j = last; j < k; ++j) {
                    ans.push_back(pre[j]);
                }
                for (int j = 0; j < k; ++j) {
                    ans.push_back(pre[j]);
                }
            }
        }
        printf("%d\n", ans.size());
        for (int i = 0; i < ans.size(); ++i) {
            if (i == ans.size() - 1) printf("%d\n", ans[i]);
            else printf("%d ", ans[i]);
        }
    }
}

C

貪心,單個字符直接k個k個放置;兩種或多個字符,若最小種字符個數k\leq k,輸出第k大的字符;兩種字符再特判一下,最小種字符正好k個,次小種按k個k個放置的情況;其餘情況,放置好前k個後直接全部排在一個字符後

char s[maxn];
map<int, int> mp;
vector< pair<int, int> >mpp;
int main()
{
    int t; scanf("%d", &t);
    while (t--) {
        int n, k; scanf("%d%d", &n, &k);
        scanf("%s", s); mp.clear(); mpp.clear();
        for (int i = 0; i < n; ++i) {
            mp[s[i] - 'a']++;
        }
        for (auto m : mp) {
            mpp.push_back(m);
        }
        if (mpp.size() == 1) {
            char ch = mpp[0].first + 'a';
            int cnt = mpp[0].second;
            int mul = cnt / k;
            if (cnt % k == 0) {
                for (int i = 0; i < mul; ++i) putchar(ch);
            }
            else for (int i = 0; i <= mul; ++i) putchar(ch);
            putchar('\n');
        }
        else {
            if (mpp[0].second < k) {
                k -= mpp[0].second;
                for (int i = 1; i < mpp.size(); ++i) {
                    if (mpp[i].second >= k) {
                        putchar(mpp[i].first + 'a');
                        putchar('\n');
                        break;
                    }
                    k -= mpp[i].second;
                }
            }
            else if (mpp[0].second > k) {
                putchar(mpp[0].first + 'a');
                for (int i = 0; i < mpp[0].second - k; ++i) putchar(mpp[0].first + 'a');
                for (int i = 1; i < mpp.size(); ++i) {
                    for (int j = 0; j < mpp[i].second; ++j)
                        putchar(mpp[i].first + 'a');
                } 
                putchar('\n');
            }
            else {
                if (mpp.size() == 2) {
                    putchar(mpp[0].first + 'a');
                    char ch = mpp[1].first + 'a';
                    int cnt = mpp[1].second;
                    int mul = cnt / k;
                    if (cnt % k == 0) for (int i = 0; i < mul; ++i) putchar(ch);
                    else for (int i = 0; i <= mul; ++i) putchar(ch);
                    putchar('\n');
                }
                else {
                    putchar(mpp[0].first + 'a');
                    for (int i = 1; i < mpp.size(); ++i) {
                        for (int j = 0; j < mpp[i].second; ++j)
                            putchar(mpp[i].first + 'a');
                    }
                    putchar('\n');
                }
            }
        }
    }
}

D

分析題意,根據分裂關係可得下個時間數量爲 [該時間數量,該時間數量x2]之間;並且總數量是前綴和關係,因此我們需要計算的就是a0+a1++ak=na_0+a_1+\dots+a_k=n,其中k最小,ai1ai2×ai1a_{i-1}\leq a_i\leq 2\times a_{i-1}
直接按2i2^i構造序列,使前綴和ain\sum a_i\leq n,若sum不足補上n-sum在排序
答案即是 構造序列的差分序列

int t; scanf("%d", &t);
while (t--) {
    int n; scanf("%d", &n);
    int sum = 0; a.clear();
    for (int i = 0; ; ++i) {
        if (1ll * sum + (1 << i) > n) break;
        sum += 1 << i;
        a.push_back(1 << i);
    }
    if (n != sum) a.push_back(n - sum);
    sort(a.begin(), a.end());
    printf("%d\n", a.size() - 1);
    for (int i = 1; i < a.size(); ++i) {
        printf("%d ", a[i] - a[i - 1]);
    }
    printf("\n");
}

E

看了很久還是不是很會,哭了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章