Codeforces Round #643 (Div. 2) A

A. Sequence with Digits

(Description:)

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

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

(Solution:)

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

  首先 (minDigit(x) imes 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)) 构成三角形,要求满足:(aleq xleq bleq yleq cleq zleq 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) imes (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 imes 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;
}




原文地址:https://www.cnblogs.com/nonameless/p/12912252.html