codeforces竞赛1114题解

A. Got Any Grapes?

AC代码:

import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner cin=new Scanner(System.in);
        int x = cin.nextInt();
        int y = cin.nextInt();
        int z = cin.nextInt();
        int a = cin.nextInt();
        int b = cin.nextInt();
        int c = cin.nextInt();
        boolean f = true;
        if(a < x){
            f = false;
        }else{
            a -= x;
            int d = a + b;
            if(d < y){
                f = false;
            }else{
                d -= y;
                if(d + c < z){
                    f = false;
                }
            }
        }
        System.out.println(f?"YES":"NO");
        cin.close();

    }
}

B. Yet Another Array Partitioning Task

题目大意:

对于一个长度为n的数组,将它划分为k个子数组,每个子数组不少于m个元素,子数组中前m大的元素和被称为这一子数组的美丽度,求这k个子数组的美丽度的和。

解题思路(贪心):

就是求这个数组的前k*m大的元素之和。
解题步骤:

  1. 将数组的值和下标作为pair键值对,放入到vector中排序(按照值的大小排序)
  2. 将排序好的数组中的前k*m个pair元素放入到一个新的集合vector中,然后按照下标排序
  3. 输出前k-1组的最后一个下标(如下代码所示)

AC代码:

#include<bits/stdc++.h>
using namespace std;
using LL = long long;
int main(){
 //  ifstream cin("input.txt");
    int n, m, k;
    cin >> n >> m >> k;
    vector<pair<int, int> >v(n);
    for(int i = 0; i < n; i++){
        cin >> v[i].first;
        v[i].second = i;
    }
    sort(v.begin(), v.end(), [](pair<int, int>pa, pair<int, int>pb)->bool{
            if(pa.first != pb.first)
                return pa.first > pb.first;
            return pa.second < pb.second;
         });
    vector<pair<int, int> > v2;
    LL cnt = 0;
    for(int i = 0; i < k * m; i++){
        cnt += v[i].first;
        v2.emplace_back(v[i]);
    }
    sort(v2.begin(), v2.end(), [](pair<int, int>pa,pair<int, int>pb)->bool{
            return pa.second < pb.second;
         });
    cout << cnt << endl;

    for(int i = m-1, t = 1; t < k;t++, i += m){
        cout << v2[i].second+1 << " ";
    }
	return 0;
}

C. Trailing Loves (or L’oeufs?)

题目大意:

将n!转化成b进制后,尾部的0有多少个

解题思路(数论):

一个数转化成b进制后尾部的0的数目,就是这个数中bkb^kbk中的k的个数。
那么我们可以将b分解成素数的乘积,即b=p1a1p2a2...pkakb = p_{1}^{a_1}*p_{2}^{a_2}*...*p_{k}^{a_k}b=p1a1​​∗p2a2​​∗...∗pkak​​,然后求出最小的b的分解中每个素数pip_ipi​的n!对应的素数分解中的倍数。n!阶乘中pip_ipi​的指数的个数为npi+npi2+...+npir\frac{n}{p_i}+\frac{n}{{p_i}^2}+...+\frac{n}{{p_i}^r}pi​n​+pi​2n​+...+pi​rn​,其中pir&lt;=n{p_i}^r&lt;=npi​r<=n。所以本题最终所求为:min(npi+npi2+...+npir)ai),1&lt;=i&lt;=kmin(\frac{\frac{n}{p_i}+\frac{n}{{p_i}^2}+...+\frac{n}{{p_i}^r)}}{a_i}),1&lt;=i&lt;=kmin(ai​pi​n​+pi​2n​+...+pi​r)n​​),1<=i<=k

AC代码:

#include<bits/stdc++.h>
using namespace std;
using LL=unsigned long long ;
int main(){
    LL n,b;
    cin>>n>>b;
    map<LL, LL> M;
    LL i = 2;
    while(i <= b / i){//此处有坑,当心乘法LL溢出,所以用除法判断
        while(b % i == 0){
            M[i]++;
            b /= i;
        }
        i++;
    }
    if(b!=1)M[b]++;
    LL gmax = ~0LL;
    for(auto p: M){
        LL a = 1;
        LL cnt = 0;
        while(a <= n/p.first){//此处有坑,当心乘法LL溢出,所以用除法判断
            a *= p.first;
            cnt += n / a;
        }
        gmax = min(gmax, cnt / p.second);
    }
    cout << gmax << endl;
    return 0;
}

D. Flood Fill

题目大意:

一个长度为n的数组c,每个位置i都有一种颜色c[i],如果连续的一段区间颜色全部相同,则说明是同一块。每次变换一块的颜色算操作一次,求将整个数组变成仅有一种颜色需要操作多少次。

解题思路(动态规划):

设将区间[l, r]变为一种颜色c[l]的最少变换次数为dp[l][r][0],
设将区间[l, r]变为一种颜色c[r]的最少变换次数为dp[l][r][1],
那么则有动态转移方程为:

dp[l-1][r][0] = min(dp[l-1][r][0], dp[l][r][k] + (t != c[l-1]));// 当r > 0
dp[l][r+1][1] = min(dp[l][r+1][1], dp[l][r][k] + (t != c[r+1]));// 当r < n-1

AC代码:

#include<bits/stdc++.h>
using namespace std;
int main(){
    //ifstream cin("input.txt");
    int n;
    cin >> n;
    vector<int>c(n);
    for(int i = 0; i < n; i++){
        cin >> c[i];
    }
    int dp[n][n][2];
    for(int i = 0; i < n; i++){
        for(int j = 0; j < n; j++){
            if(i == j){
                dp[i][j][0] = dp[i][j][1] = 0;
            }else{
                dp[i][j][0] = dp[i][j][1] = INT_MAX/2;
            }
        }
    }
    for(int r = 0; r < n; r++){
        for(int l = r; l >= 0; l--){
            for(int k = 0; k < 2; k++){
                int t = (k?c[r]:c[l]);
                if(l)
                    dp[l-1][r][0] = min(dp[l-1][r][0], dp[l][r][k] + (t != c[l-1]));
                if(r < n-1)
                    dp[l][r+1][1] = min(dp[l][r+1][1], dp[l][r][k] + (t != c[r+1]));
            }
        }
    }
    cout << min(dp[0][n-1][0], dp[0][n-1][1]) << endl;
    return 0;
}
上一篇:DAY3-平台以及运行方式


下一篇:1114 Family Property (25 分)