现在的位置: 首页 > 综合 > 正文

Codeforces Round #274 (Div. 2)

2018年01月22日 ⁄ 综合 ⁄ 共 3608字 ⁄ 字号 评论关闭

不出意外的话,打完这场就变成Expert啦.....b( ̄▽ ̄)d 掉了90sad

----------------------------------------------------------------------------------------------------------------------

A. Expression

A B C 之间添加‘+’或‘-’,还可以添加括号, 求最大值 暴力。。。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int A[100];

int main() {

    int a, b, c;
    scanf("%d%d%d", &a, &b, &c);
    A[0] = a + b + c;
    A[1] = a * b + c;
    A[2] = a + b * c;
    A[3] = a * b * c;
    A[4] = (a + b) * c;
    A[5] = a * (b + c);
    sort(A, A + 6);
    printf("%d\n", A[5]);
    return 0;
}

B. Towers

有n个由相同木块组成的塔,每次可以从一个塔的塔顶挪走一个木块到其他塔的塔顶,最多移动k次。定义E为最高的塔与最低的塔的高度差,求移动之后最小的E是多少,要移动多少步

B真的好麻烦(判断能不能整除)先输出操作再输出结果要不要开个二维数组把结果先存起来...打比赛的时候也是先打的C。

写出来了, 姿势比昨天漂亮多了。重要的就2点吧 :1,如果经过操作之后才能知道E的值,步数,就先把操作记录下来 2,关于能不能整除不用纠结,比如2 3 2 ,2 2 2,这种|值之间的差|不超过1就不用移动.

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct point{
    int num;
    int val;
    bool operator <(const point&A) const {
        return val < A.val;
    }
}p[200];
int ans[1000][2];

int main() {
    int n, k;
    scanf("%d%d", &n, &k);
    for (int i = 0; i < n; i++) {
        scanf("%d", &p[i].val);
        p[i].num = i+1;
    }
    int q = 0, i;

    for (i = 1; i <= k; i++) {
        sort (p, p+n);
        if (p[n-1].val - p[0].val > 1) {
            p[n-1].val--;
            p[0].val++;
            ans[q][0] = p[n-1].num;
            ans[q][1] = p[0].num;
            q++;
        }
        else break;
    }
    sort(p, p + n);
    printf("%d %d\n", p[n-1].val-p[0].val, i-1);
    for (int j = 0; j < q; j++)
        printf("%d %d\n", ans[j][0], ans[j][1]);
}

C. Exams

某同学要参加n次考试,这n次考试的官方时间为Ai,而该同学可以选择提前在Bi天的时候考(Bi<Ai),如果在他在Bi天考第i门课,老师会把他的考试时间记录为Ai。该同学想让老师记录的考试时间是非递减的,求他最早在哪一天能考完这n门课

感觉写cmp函数过于臃肿,学了一个重载运算符的排序,然后yy了一会儿这题,感觉和#270C很像,贪心,首尾相接如果有小的能接上就接小的,最后把链子的最后一个元素输出来

#include <cstdio>
#include <algorithm>
using namespace std;
const int N= 50100;

struct point {
    int fir, sec;
    bool operator <(const point& A) const {
         if (fir != A.fir) {
             return fir < A.fir;
         }
         else {
             return sec < A.sec;
         }
     }
}p[N];

int main() {
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
        scanf("%d%d", &p[i].fir, &p[i].sec);

    sort(p, p+n);

    int ans = p[0].sec;
    for (int i = 0; i < n; i++) {
        ans = (ans <= p[i].sec ? p[i].sec : p[i].fir);
    }
    printf("%d\n", ans);

    return 0;
}

D. Long Jumps

看了题解

首先,可能的答案只有3种0,1,2。最坏情况,在尺上加x,y就好了,所以最多加两个点

在尺上枚举所有存在的坐标,判断Ai+x,Ai-x,Ai+y,Ai-y是否分别存在,如果距离为x,y的都存在就不用加了。如果存在一个(比如Ai+x),只需要添加另一个(y)就好了

判断是否存在的方法:枚举尺上的每个点Ai,出于贪心的考虑,我们试着找一个点Bi使这点的坐标为Ai+x或Ai-x,因为多出这个Bi点,所以我们判断Bi+y,Bi-y是否存在,如果存在一个,只需要加一个点(Ai+x或Ai-x)就好了

#include <cstdio>
#include <algorithm>
using namespace std;
int A[101000];

int main() {
    
    int n, l, x, y;
    scanf("%d%d%d%d", &n, &l, &x, &y);
    for (int i = 0; i < n; i++)
        scanf("%d", A+i);

    bool okx = false, oky = false;
    for (int i = 0; i < n; i++) {
        if (A[i]-x >= 0 && binary_search(A, A+n, A[i]-x))
            okx = true;
        if (A[i]-y >= 0 && binary_search(A, A+n, A[i]-y))
            oky = true;
    }
    if (okx&&oky)  printf("0\n");
    else if (okx&&!oky) printf("1\n%d\n", y);
    else if (!okx&&oky) printf("1\n%d\n", x);
    else {
        for (int i = 0; i < n; i++) {
            if (A[i]-x >= 0) {
                if (A[i]-x-y>=0&&binary_search(A, A+n, A[i]-x-y)||
                    (A[i]-x+y<=l&&binary_search(A, A+n, A[i]-x+y))) {
                    printf("1\n%d\n", A[i]-x);
                    return 0;
                }
            }
            if (A[i]+x <= l) {
                if (A[i]+x-y>=0&&binary_search(A, A+n, A[i]+x-y)||
                    (A[i]+x+y<=l&&binary_search(A, A+n, A[i]+x+y))) {
                    printf("1\n%d\n", A[i]+x);
                    return 0;
                }
            }
        }
        printf("2\n%d %d\n", x, y);
        return 0;
    }
}

E. Riding in a Lift

题目大意是一个人在一个n层高的楼里面坐电梯,起始位置在a。如果在楼层x(x!=b)可以坐到楼层y,但要求 |x - y| < |x - b|,这样坐k次,求这人坐电梯的序列有多少种可能。

dp,有个前缀和,后缀和的优化,自己写不出来

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MOD = (int)1e9+7;

int dp[5005][5005];
int sum[10000];

int main() {
//    freopen("in.txt", "r", stdin);
    int n, a, b, k;
    scanf("%d%d%d%d", &n, &a, &b, &k);

    if (a < b) {
        dp[0][a] = 1;
        for (int i = 1; i <= b; i++)
            sum[i] = sum[i-1] + dp[0][i];

        for (int i = 1; i <= k; i++) {
            for (int j = 1; j < b; j++) 
                dp[i][j] = (sum[j+(b-j-1)/2] - dp[i-1][j] + MOD)%MOD;
            sum[0] = 0;
            for (int j = 1; j <= b; j++)
                sum[j] = (sum[j-1] + dp[i][j])%MOD;
        }
        printf("%d\n", sum[b-1]);
    }
    else {
        dp[0][a] = 1;
        for (int i = n; i > b; i--)
            sum[i] = sum[i+1] + dp[0][i];

        for (int i = 1; i <= k; i++) {
            for (int j = b+1; j <= n; j++) 
                dp[i][j] = (sum[j-(j-b-1)/2] - dp[i-1][j] + MOD) % MOD;
            sum[0] = 0;
            for (int j = n; j > b; j--)
                sum[j] = (sum[j+1] + dp[i][j])%MOD;
        }
        printf("%d\n", sum[b+1]);
    }
    return 0;
}





抱歉!评论已关闭.