Codeforces Round 929(div3)||ABCDE

A-Turtle Puzzle: Rearrange and Negate

题意

对一个数组执行两个操作:

  1. 对数组进行重新排序或保持元素顺序不变
  2. 选择连续的一段,对该段中的元素取相反数,也可以不选择任何一段,即保持所有的元素符号不变。

求进行上述操作之后数组的最大和是多少。

数据范围

t ( 1 ≤ t ≤ 1000 ) t(1≤t≤1000) t(1t1000)

n ( 1 ≤ n ≤ 50 ) n(1≤n≤50) n(1n50)

a i ( − 100 ≤ a i ≤ 100 ) a_i(-100\le a_i\le 100) ai(100ai100)

思路

遍历数组,对所有的数取非负后相加。

参考代码

void solve() {
    int n;cin >> n;
    ll ans = 0ll;
    for (int i = 0;i < n;i++) {
        ll x;cin >> x;
        if (x < 0)ans -= x;
        else ans += x;
    }
    cout << ans << '\n';
}

B-Turtle Math: Fast Three Task

题意

有一个数组,可以对数组中的数进行任意次下方两种操作:

  1. 将数移除
  2. 将该数的数值加1

求至少进行多少次上述操作,可以使数组所有元素之和是3的倍数?

数据范围

t ( 1 ≤ t ≤ 1 0 4 ) t(1≤t≤10^4) t(1t104)

n ( 1 ≤ n ≤ 1 0 5 ) n(1≤n≤10^5) n(1n105)

a i ( 1 ≤ a i ≤ 1 0 4 ) a_i(1\le a_i\le 10^4) ai(1ai104)

思路

统计数组 a a a中模3为0、1、2的数量和余数总和。记总和为 s u m sum sum,余1的数量为 x x x,余2的数量为 y y y。考虑:

  1. s u m sum sum模3为0,则不需要操作
  2. s u m sum sum模3为2,则给任意一个数加1即可,操作1次。
  3. s u m sum sum模3为1,若有余1的数,则去掉这个数即可,否则进行两次加1操作。

参考代码

void solve() {
    int n;cin >> n;
    vector<ll>aa(n);
    ll ans = 0;
    ll x = 0, y = 0;
    for (int i = 0;i < n;i++) {
        cin >> aa[i];
        aa[i] %= 3;
        ans += aa[i];
        if (aa[i] == 1)x++;
        else if (aa[i] == 2)y++;
    }
    if (ans%3 == 0) {
        cout<<0<<'\n';
    }
    else if (ans % 3 == 2) {
        cout << 1 << '\n';
    }
    else {
        if (x > 0)cout << 1 << '\n';
        else cout << 2 << '\n';
    }
}

C-Turtle Fingers: Count the Values of k

题意

给3个正整数 a , b , l a,b,l a,b,l,找出满足 l = k × a x × b y l=k\times a^x\times b^y l=k×ax×by k k k的个数, k , x , y k,x,y k,x,y均为非负整数。

数据范围

t ( 1 ≤ t ≤ 1 0 4 ) t(1≤t≤10^4) t(1t104)

a , b , l ( 2 ≤ a , b ≤ 100 , 1 ≤ l ≤ 1 0 6 ) a,b,l(2\le a,b\le 100,1\le l\le 10^6) a,b,l(2a,b100,1l106)

思路

2 20 > 1 0 6 2^{20}\gt 10^6 220>106,可知, x , y x,y x,y的范围不超过20。

预处理 a x a^x ax b y b^y by,然后暴力遍历即可。

参考代码

void solve() {
    ll a, b, l;cin >> a >> b >> l;
    vector<ll>ax, by;
    ax.push_back(1);by.push_back(1);
    for (int i = 1;ax.back() <= l;i++) {
        ax.push_back(ax.back() * a);
    }
    for (int i = 1;by.back() <= l;i++) {
        by.push_back(by.back() * b);
    }
    set<ll>k;
    for (int i = 0;i < ax.size();i++) {
        for (int j = 0;j < by.size();j++) {
            if (l%(ax[i] * by[j]) == 0) {
                k.insert(l/(ax[i] * by[j]));
            }
        }
    }
    cout << k.size() << '\n';
}

D-Turtle Tenacity: Continual Mods

题意

给数组 a a a重新排序,判断是否存在排序使得 a 1   m o d   a 2   m o d   a 3 … a n − 1   m o d   a n = 0 a_1 \text{ }mod\text{ } a_2 \text{ }mod\text{ } a_3\dots a_{n-1}\text{ }mod\text{ }a_n=0 a1 mod a2 mod a3an1 mod an=0

数据范围

t ( 1 ≤ t ≤ 1 0 4 ) t(1≤t≤10^4) t(1t104)

n ( 2 ≤ n ≤ 1 0 5 ) n(2≤n≤10^5) n(2n105)

a i ( 1 ≤ a i ≤ 1 0 9 ) a_i(1\le a_i\le 10^9) ai(1ai109)

思路

思考 x   m o d   y x\text{ }mod\text{ }y x mod y

  1. 如果 x < y x\lt y x<y,则结果还是 x x x
  2. 如果 x = y x=y x=y​,则结果是0

如果最小的数是唯一的,则一定有解;如果最小的数不唯一,考虑是否有较大的数 z z z使得 z   m o d   x ≠ 0 z\text{ }mod\text{ }x≠0 z mod x=0,如果存在,则有更小的唯一最小值,可以有解,否则无解。

参考代码

void solve() {
    int n;cin >> n;
    vector<ll>a(n);
    for (int i = 0;i < n;i++) {
        cin >> a[i];
    }
    sort(a.begin(), a.end());
    if (a[0] != a[1]) {
        cout << "YES\n";
        return;
    }
    for (int i = 1;i < n;i++) {
        if (a[i] % a[0] != 0) {
            cout << "YES\n";
            return;
        }
    }
    cout << "NO\n";
}

E-Turtle vs. Rabbit Race: Optimal Trainings

题意

训练量 k k k是连续一段时间的每天的训练量的总和,每次训练的提高值 u u u按照训练次数递减(第1次 u u u,第2次 u − 1 u-1 u1,第3次 u − 2 u-2 u2,…,第 k k k u − k + 1 u-k+1 uk+1,,提高值可以是负数),每次给定一个起始日 l l l和提高值 u u u,寻找一个最佳的结束日 r r r,使得训练提高值总和最高,如果有多个 r r r的结果提供最高训练值,选 r r r较小的那个。

数据范围

t ( 1 ≤ t ≤ 1 0 4 ) t(1≤t≤10^4) t(1t104)

n ( 1 ≤ n ≤ 1 0 5 ) n(1≤n≤10^5) n(1n105)

a i ( 1 ≤ a i ≤ 1 0 4 ) a_i(1\le a_i\le 10^4) ai(1ai104)

q ( 1 ≤ q ≤ 1 0 5 ) q(1\le q\le 10^5) q(1q105)

l , u ( 1 ≤ l ≤ n , 1 ≤ u ≤ 1 0 9 ) l,u(1\le l\le n,1\le u \le 10^9) l,u(1ln,1u109)

思路

训练提高值总量 S S S与训练量 k k k之间的关系是 S ( k ) = u × k − k × ( k − 1 ) 2 S(k)=u\times k-\frac{k\times (k-1)}{2} S(k)=u×k2k×(k1),是一个关于 k k k先增后减的函数,最高值在 k = u + 0.5 k=u+0.5 k=u+0.5处取到,由于 k k k为整数, S ( k ) S(k) S(k)的最高值应该在 u u u u + 1 u+1 u+1处取到。

  1. 在对称轴左边,二分查找在 [ l , u ] [l,u] [l,u]的范围内最靠近 u u u k k k的取值,即小于等于 u u u的最后一个 k k k值。
  2. 在对称轴右边,二分查找 [ u + 1 , n ] [u+1,n] [u+1,n]的范围内最靠近 u + 1 u+1 u+1 k k k值,即大于等于 u + 1 u+1 u+1的第一个 k k k值。

k k k值可以通过前缀和进行筛选, k = p r e [ r ] − p r e [ l − 1 ] k=pre[r]-pre[l-1] k=pre[r]pre[l1],则对 p r e pre pre数组进行二分查找 u + p r e [ l − 1 ] u+pre[l-1] u+pre[l1] u + 1 + p r e [ l − 1 ] u+1+pre[l-1] u+1+pre[l1]即可。

对比这两个值对应的 S ( k ) S(k) S(k) r r r,以及只在 l l l那天训练的效果,择优选择。

参考代码

ll f(ll u, ll k) {
    return k * u - k * (k - 1) / 2;
}

void solve() {
    int n;cin >> n;
    vector<ll>a(n + 1);
    vector<ll>pre(n + 1);
    pre[0] = 0;a[0] = 0;
    for (int i = 1;i <= n;i++) {
        cin >> a[i];
        pre[i] = pre[i - 1] + a[i];
    }
    int q;cin >> q;
    while (q--) {
        ll l, u;cin >> l >> u;
        ll x = pre[l - 1];
        int ru = upper_bound(pre.begin() + l, pre.end(), x + u) - pre.begin() - 1;
        ll ans = a[l], ansr = l;
        if (ru >= l && ru <= n) {
            if (f(u, pre[ru] - x) > ans) {
                ans = f(u, pre[ru] - x);
                ansr = ru;
            }
        }
        int ru1 = lower_bound(pre.begin() + l, pre.end(), x + u + 1) - pre.begin();
        if (ru1 >= l, ru1 <= n) {
            if (f(u, pre[ru1] - x) > ans) {
                ans = f(u, pre[ru1] - x);
                ansr = ru1;
            }
        }
        cout << ansr << ' ';
    }
    cout << '\n';
}
  • 17
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Codeforces Round 894 (Div. 3) 是一个Codeforces举办的比赛,是第894轮的Div. 3级别比赛。它包含了一系列题目,其中包括题目E. Kolya and Movie Theatre。 根据题目描述,E. Kolya and Movie Theatre问题要求我们给定两个字符串,通过三种操作来让字符串a等于字符串b。这三种操作分别为:交换a中相同位置的字符、交换a中对称位置的字符、交换b中对称位置的字符。我们需要先进行一次预处理,替换a中的字符,然后进行上述三种操作,最终得到a等于b的结果。我们需要计算预处理操作的次数。 根据引用的讨论,当且仅当b[i]==b[n-i-1]时,如果a[i]!=a[n-i-1],需要进行一次操作;否则不需要操作。所以我们可以遍历字符串b的前半部分,判断对应位置的字符是否与后半部分对称,并统计需要进行操作的次数。 以上就是Codeforces Round 894 (Div. 3)的简要说明和题目E. Kolya and Movie Theatre的要求。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Codeforces Round #498 (Div. 3) (A+B+C+D+E+F)](https://blog.csdn.net/qq_46030630/article/details/108804114)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [Codeforces Round 894 (Div. 3)A~E题解](https://blog.csdn.net/gyeolhada/article/details/132491891)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值