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个放置的情况;其余情况,放置好前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]之间;并且总数量是前缀和关系,因此我们需要计算的就是 a 0 + a 1 + ⋯ + a k = n a_0+a_1+\dots+a_k=n a0+a1++ak=n,其中k最小, a i − 1 ≤ a i ≤ 2 × a i − 1 a_{i-1}\leq a_i\leq 2\times a_{i-1} ai1ai2×ai1
直接按 2 i 2^i 2i构造序列,使前缀和 ∑ a i ≤ n \sum a_i\leq n ain,若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

看了很久还是不是很会,哭了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值