Codeforces Round #224 (Div. 2) 题解

原文链接: http://www.cnblogs.com/lalalatianlalu/p/10417888.html

C. Arithmetic Progression

    题意:有一列数,从小到大排列以后,你可以添加一个数,问你添加一个数以后,这个数列能不能变成等差数列,如果可以添加数,可以添加那几个

    思路:对于n==1|| n == 2的时候直接特判,对于大于2的情况,把数列排序以后,找到数组中相差最小的数作为公差,在此遍历有几个地方不满足,然后讨论

 代码:

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1e5 + 7;
int a[maxn];
int stk[maxn];
int top ;
int main()
{
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
    }
    sort(a + 1, a + 1 + n);
    if(n == 1){
        puts("-1");
        return 0;
    }
    if(a[1] == a[n]){
        printf("1\n");
        printf("%d\n",a[1]);
        return 0;
    }
    if(n == 2) {
        int len = a[2] - a[1];
        if(len % 2 == 0) {
            printf("3\n");
            printf("%d %d %d\n",a[1] - len, (a[1] + a[2]) / 2, a[2] + len);
        }
        else {
            printf("2\n");
            printf("%d %d\n",a[1] - len, a[2] + len);
        }
        return 0;
    }
    int minn = 0x3f3f3f3f;
    for(int i = 2; i <= n; i++) {
        minn = min(minn, a[i] - a[i - 1]);
    }
    top = 0;
    for(int i = 1; i < n; i++) {
        if(a[i] + minn == a[i + 1])continue;
        stk[++top] = i;
    }
    if(top > 1){
        puts("0");
    }
    else if(top == 0) {
        printf("2\n");
        printf("%d %d\n",a[1] - minn, a[n] + minn);
    }
    else {
        if(a[stk[1]] + 2 * minn == a[stk[1] + 1]){
            printf("1\n");
            printf("%d\n",a[stk[1]] + minn);
        }
        else {
            printf("0\n");
        }
    }
    return 0;
}
View Code

D. Ksenia and Pawns

    题意:有一张n*m的地图(2000)只有><^v# 5 中符号,#的位置可以放两个棋子,#上的棋子都不可以移动,其他符号上的棋子可以按照方向移动一格,现在你有两个棋子,问最多两个棋子可以一共移动多少步

    思路:枚举每个#作为两颗棋子最后的终点,反向向回推,维护每天路的最大值,以及全局的最大值和次大值,如果全局最大值和次大值相等,答案就是二倍的最大值,否则答案是最大值*2 – 1,即放两个相邻的棋子,走到最后

    代码:

#include <bits/stdc++.h>
using namespace std;

const int maxn = 2007;
int n, m;
char mp[maxn][maxn];

int max1, max2;
int cnt;
int dx[10] = {0, 0, 1, -1};
int dy[10] = {-1, 1, 0, 0};
char s[10] = {'>', '<', '^', 'v'};

void Max(int x)
{
    if(x > max1) {
        max1 = x;
    }
    else if(x > max2) {
        max2 = x;
    }
}
int dfs(int x, int y)
{
    int ans = 0;
    cnt ++;
    for(int i = 0; i < 4; i++) {
        int xx = dx[i] + x, yy = dy[i] + y;
        if(xx < 1 || xx > n || yy < 1 || yy > m || (mp[xx][yy] != s[i]))continue;
        if(mp[x][y] == '#') Max(dfs(xx, yy));
        else ans = max(ans, dfs(xx, yy));
    }
    return ans + 1;
}
int main()
{
    scanf("%d%d%", &n, &m);
    for(int i = 1;i <= n; i++) {
        for(int j = 1; j <= m; j++) {
            cin >> mp[i][j];
        }
    }
    max1 = 0, max2 = 0;
    cnt = 0;
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= m; j++) {
            if(mp[i][j] == '#') {
                dfs(i, j);
            }
        }
    }
    if(cnt < n * m) {
        puts("-1");
    }
    else {
        printf("%d\n",max1 == max2 ? max1 * 2: max1 * 2 - 1);
    }
    return 0;
}
View Code

E. Ksenia and Combinatorics

    题意:有n(50)个点,让你构造出一个树满足下列条件,

1有n个点,标号为1~n

2根的度数最多为2,除了根之外的点的度数最多为3

3树的最大匹配数不超过k

问能构造出多少颗,答案对1e9+7取模

    思路:定义dp[i][j][0|1]表示用i个点,构造最大匹配数为j的dp[i][j][0]表示没有子节点连接根,[1]表示有子节点连接根,然后枚举树的左节点个数和右节点个数,以及左右节点是否是连接根的

    dp[i][j][0] += dp[l][k][1] * dp[r][j – k][1] * res

    dp[i][j][1] += dp[l][k][1] * dp[r][j – k -1] [0]* res

    dp[i][j][1] += dp[l][k][0] * dp[r][j – k -1] [1]* res

    dp[i][j][1] += dp[l][k][0] * dp[r][j – k -1] [0]* res

代码:

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
const int maxn = 57;
const int MOD = 1e9 + 7;
const int inv2 = 500000004;
int c[maxn][maxn];
int n, k;
LL dp[maxn][maxn][2];

LL mod(LL x)
{
    if(x >= MOD) return x % MOD;
    return x;
}
int main()
{
    c[0][0] = 1;
    for(int i = 1; i <= 50; i++) {
        c[i][0] = c[i][i] = 1;
        for(int j = 1; j < i; j++) {
            c[i][j] = mod(c[i - 1][j - 1] + c[i - 1][j]);
        }
    }
    scanf("%d%d", &n, &k);
    if(k > n/2){
        printf("0\n");
        return 0;
    }
    dp[1][0][0] = dp[0][0][1] = 1;
    for(int i = 1; i <= n; i++) {
        for(int j = 0; j <= k; j++) {
            for(int l = 0,r = i - 1; l <= r; l++, r--) {
                for(int k = 0; k <= j; k++) {
                    LL res = 1;
                    res = c[i - 1][l];
                    if(l == r) res = mod(res * inv2);
                    if(l) res = mod(mod(res * l) * r);
                    else res = mod(res * r);
                    dp[i][j][0] = mod(dp[i][j][0] + mod(mod(dp[l][k][1] * dp[r][j - k][1]) * res));
                    if(k < j) {
                        dp[i][j][1] = mod(dp[i][j][1] + mod(mod(dp[l][k][1] * dp[r][j - k - 1][0]) * res));
                        dp[i][j][1] = mod(dp[i][j][1] + mod(mod(dp[l][k][0] * dp[r][j - k - 1][1]) * res));
                        dp[i][j][1] = mod(dp[i][j][1] + mod(mod(dp[l][k][0] * dp[r][j - k - 1][0]) * res));
                    }
                }
            }
        }
    }
    printf("%d\n",mod(dp[n][k][0] + dp[n][k][1]));
    return 0;
}
View Code

转载于:https://www.cnblogs.com/lalalatianlalu/p/10417888.html

猜你喜欢

转载自blog.csdn.net/weixin_30498921/article/details/94926193