Codeforces Round 836题解(A、B、C)

A. SSeeeeiinngg DDoouubbllee

直接将原字符串翻转一下拼到原字符串的后面就构成了回文串。

string s;

void solve() {
    cin >> s;
    cout << s;
    reverse(s.begin(), s.end());
    cout << s << '\n';
}

B. XOR = Average

n n n的奇偶性考虑,若 n n n为奇数,我们可以让所有的 a i a_i ai相等,这样 a 1 ⨁ a 2 ⨁ ⋯ ⨁ a n = a 1 = n ⋅ a 1 n a_1 \bigoplus a_2 \bigoplus \cdots \bigoplus a_n = a_1 = \frac{n \cdot a_1}{n} a1a2an=a1=nna1。若 n n n为偶数,我们可以考虑可否将 n n n为奇数时的某个 a i a_i ai拆成两个 a i 1 a_{i_1} ai1 a i 2 a_{i_2} ai2,使得 a i 1 ⨁ a i 2 = a i a_{i_1} \bigoplus a_{i_2} = a_i ai1ai2=ai并且 a i 1 + a i 2 2 = a i \frac{a_{i_1} + a_{i_2}}{2} = a_i 2ai1+ai2=ai,这样就仍然满足 a 1 ⨁ a 2 ⨁ ⋯ ⨁ a n = a 1 = n ⋅ a 1 n a_1 \bigoplus a_2 \bigoplus \cdots \bigoplus a_n = a_1 = \frac{n \cdot a_1}{n} a1a2an=a1=nna1。容易发现 1 1 1 3 3 3就刚好满足这样的限制, 1 ⨁ 3 = 2 1 \bigoplus 3 = 2 13=2并且 1 + 3 2 = 2 \frac{1 + 3}{2} = 2 21+3=2

int n;

void solve() {
    cin >> n;
    if (n & 1) {
        for (int i = 1; i <= n; i ++) {
            cout << 1 << ' ';
        }
        cout << '\n';
    }
    else {
        cout << 1 << ' ' << 3 << ' ';
        for (int i = 1; i <= n - 2; i ++) {
            cout << 2 << ' ';
        }
        cout << '\n';
    }
}

C. Almost All Multiples

如果 1 1 1这个位置放的是 n n n,那么一定是可以构造出来一个排列的,并且字典序最小的排列就是除了 1 1 1 n n n这两个位置外的其他位置 i i i都放 i i i

排放形式如下:
n 2 3 4 5 6 7 8 9 10 11 1( n n n 12 12 12的情况)

如果 1 1 1这个位置放的不是 n n n,譬如说是 x x x,那么我们就必须把 x x x这个位置后面的是 x x x的倍数的数放到 x x x这个位置,并在那个数的位置上放上新的数。

那么如果 n n n不是 x x x的倍数,则 n n n也不会是 x ∗ 2 , x ∗ 3 , ⋯ x * 2, x * 3, \cdots x2,x3,这些数的倍数,则我们按照上述的规则移动了一些数的位置后,最后 n n n就无法用来补上最后移动的那个数所空缺下来的位置,所以这种情况下应该输出 − 1 -1 1

贪心地考虑,当 n n n x x x的倍数时,我们可以选择形如 x , x ∗ 2 , x ∗ 2 ∗ 3 , x ∗ 2 ∗ 5 , n x, x * 2, x * 2 * 3, x * 2 * 5, n x,x2,x23,x25,n这些位置,将这些位置上的数向左移动一位,最后把 n n n补到最后一位。显然,将 n x \frac{n}{x} xn分解质因数,可以使乘的倍数的次数最大化,即让字典序较小的数字更多地靠前,且按照质因数从小到大的顺序乘,即让字典序越小的数越靠前。这样得到的排列就是最优的。

对于 n = 12 n = 12 n=12举例, x = 4 x = 4 x=4的话,所求排列就是这样的:

4 2 3 12 5 6 7 8 9 10 11 1

int n, x;

void solve() {
    cin >> n >> x;
    if (n % x != 0) {
        cout << -1 << '\n';
        return;
    }
    int y = n / x;
    vector<int> bag;
    for (int i = 2; i <= y / i; i ++) {
        if (y % i == 0) {
            while (y % i == 0) {
                bag.push_back(i);
                y /= i;
            }
        }
    }
    if (y > 1) bag.push_back(y);
    vector<int> ans(n + 1, 0);
    for (int i = 1; i <= n; i ++) {
        ans[i] = i;
    }
    ans[1] = x, ans[n] = 1;
    int cur = x;
    for (int i = 0; i < (int)bag.size(); i ++) {
        int t = cur;
        cur *= bag[i];
        ans[t] = cur;
    }
    for (int i = 1; i <= n; i ++) {
        cout << ans[i] << ' ';
    }
    cout << '\n';
}
  • 18
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值