Codeforces Round #667 (Div. 3)

Codeforces Round #667 (Div. 3)

A.Yet Another Two Integers Problem

题意: 给定a和b,每次可以把a+k或者a-k, k ∈ [ 1 , 10 ] k \in [1, 10] k[1,10],求最少变化多少次能够使得a变成b
题解: 计算出a和b的差值,然后向上取整即可
代码:

#include <bits/stdc++.h>

using namespace std;

int const N = 2e5 + 10;
int T, n, a[N];

int main() {
    cin >> T;
    while(T--) {
        int a, b;
        cin >> a >> b;
        int diff = abs(b - a);
        // cout << ceil((double)diff/10)<<endl;
        printf("%d\n", (int)ceil((double)diff/10));
    }
    return 0;
}

B.Minimum Product

题意: 给定a,b,x,y,n,每次操作可以让a–或者b–,但是a最小减到x,b最小减到y,操作次数最多为n次,问a和b经过若干次操作后,a*b的值最小是多少
题解: 假设a经过若干次后为a’,b经过若干次后为b’,则答案为res = a’*b’。要让res最小,那么a’和b’的差值要尽可能大。那么如何让差值尽可能大呢,要让小的尽可能小。但是由于x和y的限制,直接把较小的那个变化,不能达到最优值。因此,一种情况是把较小的减小,另一种是把较大的减的比原先较小的还要小。
代码:

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
int const N = 2e5 + 10;
int T, n, a, b, x, y;

LL solve(int a, int b, int x, int y, int n) {
    int diff_a = min(n, a - x);
    a -= diff_a;
    n -= diff_a;
    
    int diff_b = min(n, b - y);
    b -= diff_b;
    return a * 1ll * b;
}

int main() {
    cin >> T;
    while(T--) {
        scanf("%d%d%d%d%d", &a, &b, &x, &y, &n);
        cout << min(solve(a, b, x, y, n), solve(b, a, y, x, n)) << endl;
    }
    return 0;
}

C.Yet Another Array Restoration

题意: 给定等差数列中的两项,给定等差数列的项数,构造一个等差数列,且使得最大值最小
题解: 由于数字较小,都不超过50,因此直接暴力即可。暴力枚举等差数列的公差,然后每次都判断最大值,求出最小的情况即可
代码:

#include <bits/stdc++.h>

using namespace std;

int const N = 1e5 + 10;
int T, n, ai[N];
vector<int> res, tmp;
int a, b;
int minv = N;

void slove(int det) {
    tmp.clear();
    if (b - det * (n - 1) > 0 && b - det * (n - 1) <= a) {
        // if (det == 10) cout << "here" << endl;
        for (int i = b - det * (n - 1); i <= b; i += det) {
            // if (det == 10) cout << "push: " << i << endl;
            tmp.push_back(i);
        }
        if (b < minv) {
            minv = min(minv, b);
            res = tmp;
        }
    }
    else if (b - det * (n - 1) <= a) {
        int t = b;
        int cnt = 0;
        while(t - det > 0) {
            cnt ++;
            t -= det; 
        } 
        for (int i = t, j = 0; j < n; ++j, i += det) tmp.push_back(i);
        if (tmp.back() < minv) {
            minv = min(minv, tmp.back());
            res = tmp;
        }
    }
    // return 1;
}

int main() {
    cin >> T;
    while(T--) {
        res.clear();
        tmp.clear();
        scanf("%d%d%d", &n, &a, &b);
        if (n == 2 ) {
            cout << a << " " << b << endl;
            continue;
        }
        minv = N;
        int diff = b - a;
        for (int i = 1; i <= diff; ++i) {
            if (diff % i == 0) 
                slove(i);
        }
        for (auto r: res) cout << r << " " ;
        printf("\n");
    }
    return 0;
}

D.Decrease the Sum of Digits

题意: 给定n和s,每次操作可以把n += 1,求至少操作多少次后能够使得n的每位数字之和小于等于s。
题解: 记n得每位之和为sum(n),如果sum(n) <= s,那么输出0;否则从最低为开始(为了保证操作次数尽可能小),如果当前sum(n)>s,那么把n得当前位数+1,直到进位(不进位的话sum(n)只增不减)。
代码:

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
int const N = 2e5 + 10;
LL T, n, s;

LL check(LL x) {
    LL sum = 0;
    while(x) {
        sum += x % 10;
        x /= 10;
    }
    return sum;
}

int main() {
    cin >> T;
    while(T--) {
        scanf("%lld%lld", &n, &s);
        if (check(n) <= s) {
            printf("0\n");
            continue;
        }
        LL res = 0, bit = 1;
        for (int i = 0; i < 18; ++i) {
            LL last = n / bit % 10;
            LL add = (10 - last) * bit;
            res += add;
            n += add;
            if (check(n) <= s) break;
            bit *= 10;
        }
        printf("%lld\n", res);
    }
    return 0;
}

E. Two Platforms

题意: 给定一张竖直平面上n个点,每个点坐标位(xi, yi),给定2个板子,板子的长度均为k。问将两个板子放置在哪可以保证两个板子接到的点数和最多。 ∑ n < = 2 ∗ 1 0 5 , x i < = 1 0 9 , y i < = 1 0 9 , 1 < = k < = 1 0 9 \sum n <= 2*10^5, x_i<=10^9, y_i <= 10^9, 1 <= k <= 10^9 n<=2105,xi<=109,yi<=109,1<=k<=109
题解: 动态规划处理,r[i]表示用一块板子在i右侧能够接到的点最多为多少,l[i]表示用一块板子在i左侧能够接到的点最多为多少。那么答案就是 r e s = m a x { l [ i ] + r [ i + 1 ] } 。 res = max\lbrace l[i] + r[i + 1] \rbrace 。 res=max{l[i]+r[i+1]}本题点的坐标到达 1 0 9 10^9 109,本来应该离散化,但是可以特殊处理、利用尺取的思想就可以避免离散化,具体见代码。
代码:

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
int const N = 2e5 + 10;
int T, n, x[N], k, l[N], r[N];

int main() {
    cin >> T;
    while(T--) {
        memset(l, 0, sizeof l);
        memset(r, 0, sizeof r);
        scanf("%d%d", &n, &k);
        for (int i = 1; i <= n; ++i) scanf("%d", &x[i]);
        for (int i = 1, t; i <= n; ++i) scanf("%d", &t);
        if (n == 1) {
            printf("1\n");
            continue;
        }
        sort(x + 1, x + 1 + n);
        int j = n;
        for (int i = n; i >= 1; --i) {
            while(x[j] - x[i] > k && j >= i) j--;
            r[i] = j - i + 1;
            if (i < n) r[i] = max(r[i], r[i + 1]);
        }
        
        j = 1; 
        for (int i = 1; i <= n; ++i) {
            while(x[i] - x[j] > k && j <= i) ++j;
            l[i] = i - j + 1;
            if (i > 1) l[i] = max(l[i], l[i - 1]);
        }
        
        int res = 1;
        for (int i = 1; i < n; ++i) {
            res = max(res, l[i] + r[i + 1]);
        }
        printf("%d\n", res);
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值