Codeforces Round #643 (Div. 2) A - E 解题报告

A. Sequence with Digits

\(Description:\)

  定义: \(a_{n + 1} = a_n + minDigit(a_n) \times maxDigit(a_n)\)

  给定 \(a_1\)\(k\),求 \(a_k\)

\(Solution:\)

  显然当 \(a_n\) 中包含了 \(0\) 时,之后的数都等于 \(a_n\)。那么我们就要判断是否一定会出现包含 \(0\) 的情况,并且复杂度是可以接受的。

  首先 \(minDigit(x) \times maxDigit(x) \leq 81\)。那么令 \(t = x\ mod\ 1000\),那么 \(t < 1000\),那么在经过递增过后,一定会出现 \(t + m \geq 1000\),由于 \(m \leq 81\),那么 \(t + m < 1100\),也就是一千零几,那么他的百位一定是 \(0\)。所以我们是可以直接循环去解决。

\(Code:\)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;

ll calc(ll num){
    ll Min = 9, Max = 0;
    while(num){
        Min = min(Min, num % 10);
        Max = max(Max, num % 10);
        num /= 10;
    }
    return Min * Max;
}

int main(){
    int t; cin >> t;
    while(t --){
        ll a, k;
        cin >> a >> k;
        for(int i = 2; i <= k; i ++){
            a = a + calc(a);
            if(calc(a) == 0) break;
        }
        cout << a << endl;
    }
    return 0;
}



B. Young Explorers

\(Description:\)

  给定长度为 \(n\) 的数组 \(e\),进行分组,要求 \(e_i \leq\) 该组的人数,问最多分几组?

\(Solution:\)

  从小到大排个序,从左边到右边遍历一遍,能组成一组就组成一组。

\(Code:\)

//http://codeforces.com/contest/1355/problem/B
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
const double PI  = acos(-1.0);
const double eps = 1e-8;
const int INF = 0x3f3f3f3f;
const ll LNF  = 0x3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
inline ll  gcd(ll  a, ll b)  { return b ? gcd(b, a % b) : a; }
inline int lcm(int a, int b) { return a * b / gcd(a, b); }

const int N = 3e5 + 10;

int e[N];

int main(){

    int t; cin >> t;
    while(t --){
        int n; cin >> n;
        for(int i = 1; i <= n; i ++)
            scanf("%d", &e[i]);
        sort(e + 1, e + n + 1);
        int ans = 0;
        int cnt = 0; // 记录当前组的人数
        for(int i = 1; i <= n; i ++){
            cnt ++;
            if(e[i] <= cnt){ // 符合要求了
                cnt = 0;
                ans ++;
            }
        }
        cout << ans << endl;
    }
    return 0;
}




C. Count Triangles

\(Description:\)

  给定 \(a,\ b,\ c,\ d\),问有多少组 \((x,\ y,\ z)\) 构成三角形,要求满足:\(a\leq x\leq b\leq y\leq c\leq z\leq d\)

\(Solution:\)

  枚举 \(x\),由于 \(x + y > z\) 并且 \(z \geq c\),那么 \(y_{min} = max(b,\ c - x + 1)\) 才能符合要求;当 \(x + y > d\) 之后,\(z\) 的选择始终为 \(d - c + 1\) 个,那么我们计算出 \(y_{max} = max(b,\ d - x + 1)\)。那么我们就可以分两段计算:\([y_{min},\ y_{max} - 1]\)\([y_{max}, c]\)

  对于 \([y_{min}, y_{max} - 1]\)\(\sum_{i = y_{min}}^{y_{max}-1}\ (x + y_i - c)\)\((x + y_i - c)\) 就是 \(z\) 可以选择的个数。而这显然是等差数列求和。

  对于 \([y_{max}, c]\)\((c - y_{max} + 1) \times (d - c + 1)\)

\(Code:\)

//http://codeforces.com/contest/1355/problem/C
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
const double PI  = acos(-1.0);
const double eps = 1e-8;
const int INF = 0x3f3f3f3f;
const ll LNF  = 0x3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
inline ll  gcd(ll  a, ll b)  { return b ? gcd(b, a % b) : a; }
inline int lcm(int a, int b) { return a * b / gcd(a, b); }

int main(){

    // a <= x <= b <= y <= c <= z <= d

    ll a, b, c, d;
    cin >> a >> b >> c >> d;

    ll ans = 0;
    for(ll x = a; x <= b; x ++){
        ll yMin = max(b, c - x + 1);
        ll yMax = max(b, d - x + 1);
        ans += max(c - yMax + 1, 1ll * 0) * (d - c + 1); // 有可能 yMax > c
        yMax = min(yMax - 1, c);
        ans += (yMax - yMin + 1) * (2 * (x - c) + yMin + yMax) / 2;
    }

    cout << ans << endl;


    return 0;
}




D. Game With Array

\(Description:\)

  能否构造出一个数组,使得数组中任意一段区间的和不为 \(k\)\(s - k\)\(s\) 为数组的和。( \(k\) 自选)

\(Solution:\)

  对于 \(n = 1\) 的情况很容易判断。

  对于 \(n \geq 2\):构造出不含 \(1\) 的数组,令 \(k = 1\) 即可符合要求。那么也就是数组每一项最少为 \(2\),也就是说 \(s \leq 2 \times n - 1\) 的不行。

\(Code:\)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
const double PI  = acos(-1.0);
const double eps = 1e-8;
const int INF = 0x3f3f3f3f;
const ll LNF  = 0x3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
inline ll  gcd(ll  a, ll b)  { return b ? gcd(b, a % b) : a; }
inline int lcm(int a, int b) { return a * b / gcd(a, b); }


int main(){
    
    int n, s;
    cin >> n >> s;
    if(n == 1){
        if(s == 1) puts("NO");
        else{
            puts("YES");
            cout << s << endl;
            cout << s - 1 << endl;
        }
    }else{
        if(s <= 2 * n - 1) puts("NO");
        else{
            puts("YES");
            for(int i = 1; i < n; i ++)
                printf("2 ");
            cout << s - 2 * (n - 1) << endl;
            cout << 1 << endl;
        }
    }
    return 0;
}




E. Restorer Distance

\(Description:\)

  给出长度为 \(n\) 的数组 \(h\),要求使数组中的数都相同。

  有三种操作:

    \(1.\) 使某个数加 \(1\),花费 \(a\)

    \(2.\) 使某个数减 \(1\),花费 \(r\);

    \(3.\) 选择两个数,一个加 \(1\),一个减 \(1\),花费 \(m\)

  求最少代价?

\(Solution:\)

  我们枚举最终的高度,可以想到的是代价一定是随高度变化的一个二次函数。那么直接三分就可以轻易求解。

\(Code:\)

//http://codeforces.com/contest/1355/problem/E
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
const double PI  = acos(-1.0);
const double eps = 1e-8;
const int INF = 0x3f3f3f3f;
const ll LNF  = 0x3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
inline ll  gcd(ll  a, ll b)  { return b ? gcd(b, a % b) : a; }
inline int lcm(int a, int b) { return a * b / gcd(a, b); }

const int N = 1e5 + 10;

int n, a, r, m;
int h[N];
ll sum[N];

ll check(int mid){
    ll more = 0, less = 0;
    for(int i = 1; i <= n; i ++){
        if(h[i] < mid) less += mid - h[i];
        if(h[i] > mid) more += h[i]- mid;
    }
    ll res = min(less, more) * m;
    if(less > more) res += a * (less  - more);
    else res += r * (more - less);
    return res;
}

int main(){

    cin >> n >> a >> r >> m;
    for(int i = 1; i <= n; i ++)
        scanf("%d", &h[i]);
    sort(h + 1, h + n + 1);

    m = min(m, a + r);

    int le = h[1], ri = h[n];
    ll ans = LNF;
    while(le <= ri){
        int lmid = le + (ri - le) / 3;
        int rmid = ri - (ri - le) / 3;
        ll costl = check(lmid);
        ll costr = check(rmid);
        if(costl < costr){
            ans = costl;
            ri = rmid - 1;
        }else{
            ans = costr;
            le = lmid + 1;
        }
    }

    cout << ans << endl;
    
    return 0;
}




猜你喜欢

转载自www.cnblogs.com/nonameless/p/12912252.html