8VC Venture Cup 2016 - Elimination Round

在家补补题

 

模拟 A - Robot Sequence

#include <bits/stdc++.h>

char str[202];

void move(int &x, int &y, char ch)  {
    if (ch == ‘U‘)  x--;
    if (ch == ‘D‘)  x++;
    if (ch == ‘L‘)  y--;
    if (ch == ‘R‘)  y++;
}

int main(void)  {
    int n;  scanf ("%d", &n);
    scanf ("%s", &str);
    int ans = 0;
    for (int i=0; i<n; ++i) {
        int x = 0, y = 0;
        for (int j=i; j<n; ++j) {
            move (x, y, str[j]);
            if (x == 0 && y == 0)   ans++;
        }
    }
    printf ("%d\n", ans);

    return 0;
}

暴力 || 找规律 B - Cards

暴力即DFS也行。。。当时就if else乱写一堆过了

#include <bits/stdc++.h>

char str[202];
int col[3];

int main(void)  {
    int n;  scanf ("%d", &n);
    scanf ("%s", &str);
    col[0] = col[1] = col[2] = 0;
    for (int i=0; i<n; ++i) {
        if (str[i] == ‘R‘)  col[0]++;
        if (str[i] == ‘G‘)  col[1]++;
        if (str[i] == ‘B‘)  col[2]++;
    }
    if (col[0] == n)    puts ("R");
    else if (col[1] == n) puts ("G");
    else if (col[2] == n)   puts ("B");
    else    {
        if (col[0] && col[1] && col[2]) puts ("BGR");
        else    {
            if (n == 2) {
                if (col[0] == 0)    puts ("R");
                else if (col[1] == 0)   puts ("G");
                else if (col[2] == 0)   puts ("B");
            }
            else if (col[0] == 1)   {
                if (col[1] == 0)    puts ("GR");
                if (col[2] == 0)    puts ("BR");
            }
            else if (col[1] == 1)   {
                if (col[0] == 0)    puts ("GR");
                if (col[2] == 0)    puts ("BG");
            }
            else if (col[2] == 1)    {
                if (col[0] == 0)    puts ("BR");
                if (col[1] == 0)    puts ("BG");
            }
            else    puts ("BGR");
        }
    }

    return 0;
} 

暴力 C - Block Towers

直接枚举答案,同时记录能整除2,整除2和3,只能整除3的个数,当遇到满足条件的就是最优。二分也行。。

#include <bits/stdc++.h>

const int N = 4e6 + 5;

int main(void)  {
    int n, m;   scanf ("%d%d", &n, &m);
    int best = 4000000;
    int c1 = 0, c2 = 0, c3 = 0;
    for (int i=2; i<=4000000; ++i) {
        if (i % 2 == 0) c1++;
        if (i % 2 == 0 && i % 3 == 0)   c2++;
        if (i % 2 != 0 && i % 3 == 0) c3++;
        if (c1 >= n && c2 >= m - c3 && c1 - (m - c3) >= n)  {
            best = i;   break;
        }
    }
    printf ("%d\n", best);

    return 0;
}

暴力+概率 D - Jerry‘s Protest

题意:已知结果两胜一负,问总和小于后者的概率。

分析:预处理出任意两个数字相减的差的方案数,那么前两次在正数选,后者只要能使得总和小的可以处理前缀和,O (1),总复杂度 O (n ^ 2)。

#include <bits/stdc++.h>

const int N = 2e3 + 5;

int a[N];
int cnt[10005];
int sum[5005];

int main(void)  {
    int n;  scanf ("%d", &n);
    for (int i=1; i<=n; ++i)    scanf ("%d", &a[i]);
    for (int i=1; i<=n; ++i)    {
        for (int j=1; j<=n; ++j)    {
            if (i == j) continue;
            cnt[5000+a[i]-a[j]]++;
        }
    }
    for (int i=1; i<=5000; ++i) {
        sum[i] = sum[i-1] + cnt[i];
    }
    double ans = 0;
    for (int i=5001; i<=9999; ++i)  {
        if (!cnt[i])    continue;
        for (int j=5001; j<=9999; ++j)  {
            if (!cnt[j])    continue;
            int c = 15000 - (i + j) - 1;
            if (c < 1 || c > 4999 || !sum[c])  continue;
            ans += 1.0 * cnt[i] * cnt[j] * sum[c];
        }
    }
    double div = 1.0 * (n * (n - 1) / 2);
    ans = ans / div / div / div;
    printf ("%.8f\n", ans);

    return 0;
}

三分 + 贪心 E - Simple Skewness

题意:选取一个子集使得平均数-中位数最大

分析:首先个数是奇数,如果是偶数,去掉中间较大的数,差会变大(?)。然后排序后,枚举中位数的位置,三分长度,因为差的分布是单峰,选的数字使差尽可能大,右边选择最后几个,左边选取靠近中位数的几个。

#include <bits/stdc++.h>

typedef long long ll;
const int N = 2e5 + 5;
struct Pair {
    ll a;   int b;
    bool operator < (const Pair &rhs) const {
        return a * rhs.b < rhs.a * b;
    }
};
int a[N];
ll sum[N];
int n, bi, bl;
Pair best;

Pair get(int id, int len)   {
    ll val = sum[id] - sum[id-len-1];
    val += sum[n] - sum[n-len];
    Pair cur = Pair {val, 2 * len + 1};
    cur.a -= 1ll * a[id] * cur.b;
    if (best < cur) {
        best = cur;
        bi = id;    bl = len;
    }
    return cur;
}

int main(void)  {
    scanf ("%d", &n);
    for (int i=1; i<=n; ++i)    {
        scanf ("%d", a + i);
    }
    std::sort (a+1, a+1+n);
    for (int i=1; i<=n; ++i)    {
        sum[i] = sum[i-1] + a[i];
    }
    bi = 1; bl = 0;
    best = Pair {0, 1};
    for (int i=1; i<=n; ++i)    {
        int low = 0, high = std::min (i - 1, n - i);
        while (low + 3 < high)  {
            int mid1 = (2 * low + high) / 3;
            int mid2 = (low + 2 * high) / 3;
            Pair v1 = get (i, mid1);
            Pair v2 = get (i, mid2);
            if (v1 < v2)    low = mid1;
            else    high = mid2;
        }
        for (int j=low; j<=high; ++j)   get (i, j);
    }
    std::vector<int> ans;
    for (int i=bi-bl; i<=bi; ++i)   {
        ans.push_back (a[i]);
    }
    for (int i=n-bl+1; i<=n; ++i)  {
        ans.push_back (a[i]);
    }
    printf ("%d\n", ans.size ());
    for (int i=0; i<ans.size (); ++i)   {
        if (i > 0)  putchar (‘ ‘);
        printf ("%d", ans[i]);
    }
    puts ("");

    return 0;
} 

DP F - Group Projects

题意:n个数字分组,求每组最大值-最小值的和小于k的方案数

分析:明显的DP,复杂度肯定是 O (n ^ 2 * k),难在状态的转移。dp[i][j][k] 考虑前i个数字,open(只知道最小值,最大值未知)了j组,当前累计和为k的方案数。那么open的几组暂时由a[i]"托管",之前是a[i-1]“托管”,那么前后转移累加j * (a[i] - a[i-1]),a[i]有好几种选择,可以close一个组,选择一个组自己为最大值,j - 1;可以多一个组,自己为最小值,j+1;还可以进入某一个组(自己不是最大值)或者自己一个数字成为一个组(不算open)。

#include <bits/stdc++.h>

const int N = 2e2 + 5;
const int K = 1e3 + 5;
const int MOD = 1e9 + 7;
int a[N];
int dp[2][N][K];

void add(int &x, int y) {
    x += y;
    if (x >= MOD)   x %= MOD;
}

int main(void)  {
    int n, m;   scanf ("%d%d", &n, &m);
    for (int i=1; i<=n; ++i)    scanf ("%d", a + i);
    std::sort (a+1, a+1+n);
    int now = 0;
    dp[now][0][0] = 1;
    for (int i=1; i<=n; ++i)    {
        now ^= 1;
        memset (dp[now], 0, sizeof (dp[now]));
        for (int j=0; j<i; ++j) {
            for (int k=0; k<=m; ++k)    {
                if (!dp[now^1][j][k])    continue;
                int &x = dp[now^1][j][k];
                int s = k + j * (a[i] - a[i-1]);
                if (s > m)  continue;
                add (dp[now][j][s], 1ll * x * (j + 1) % MOD);
                add (dp[now][j+1][s], x);
                if (j)  add (dp[now][j-1][s], 1ll * x * j % MOD);
            }
        }
    }
    int ans = 0;
    for (int i=0; i<=m; ++i)    add (ans, dp[now][0][i]);
    printf ("%d\n", ans);

    return 0;
}

  

时间: 2024-10-12 11:33:55

8VC Venture Cup 2016 - Elimination Round的相关文章

codeforces 8VC Venture Cup 2016 - Elimination Round C. Lieges of Legendre

C. Lieges of Legendre 题意:给n,m表示有n个为2的倍数,m个为3的倍数:问这n+m个数不重复时的最大值 最小为多少? 数据:(0 ≤ n, m ≤ 1 000 000, n + m > 0) ps:很水的题,主要是策略: 思路:由于里面每隔6就会重复一次,不好直接模拟,并且模拟的效率很低,那就二分吧!二分即上界为2单独的最大倍数与3单独时的最大倍数之和,下界为前面二者的max;之后利用判断是否mid/2 >= n && mid/3 >= m &am

8VC Venture Cup 2016 - Elimination Round E. Simple Skewness(枚举+三分)

题目链接:点击打开链接 题意:给你n个数, 要求选若干个数, 使得这些数的平均数减去中位数尽量大. 思路:由于该题没有顺序问题, 排好序之后我们可以枚举中位数, 可以证明, 奇数个数一定比偶数优,然后三分中位数左右区间长度x(数的个数), 在中位数的右边选最大的x个数, 在左边也选最大的x个, 这样, 随着区间长度的增加, 平均数将先增大后减小, 或者一直减小,或者一直增大. 为什么呢? 假设第一次的区间长度是1, 那么我们选择了两边最大的两个数, 假设他们加起来取平均大于中位数, 那么对答案有

Codeforces 8VC Venture Cup 2016 - Elimination Round F. Group Projects 差分DP*****

F. Group Projects There are n students in a class working on group projects. The students will divide into groups (some students may be in groups alone), work on their independent pieces, and then discuss the results together. It takes the i-th stude

8VC Venture Cup 2016 - Final Round (Div2) E

贪心.当前位置满油可达的gas station中,如果有比它小的,则加油至第一个比他小的.没有,则加满油,先到达这些station中最小的.注意数的范围即可. #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define LL long long using namespace std; const int MAXN = 200050; int d,

Codeforces Round #393 (Div. 2) (8VC Venture Cup 2017 - Final Round Div. 2 Edition) E - Nikita and stack 线段树好题

http://codeforces.com/contest/760/problem/E 题目大意:现在对栈有m个操作,但是顺序是乱的,现在每输入一个操作要求你输出当前的栈顶, 注意,已有操作要按它们的时间顺序进行. 思路:线段树好题啊啊,我们把push当成+1, pop当成-1,按操作的位置建立线段树,那么如何 寻找栈顶呢,我们计算每个点的后缀,栈顶就是下标最大的>0的后缀,我们拿后缀建立线段树, 剩下的就是区间加减法,和求区间最大值啦. #include<bits/stdc++.h>

CF #CROC 2016 - Elimination Round D. Robot Rapping Results Report 二分+拓扑排序

题目链接:http://codeforces.com/contest/655/problem/D 大意是给若干对偏序,问最少需要前多少对关系,可以确定所有的大小关系. 解法是二分答案,利用拓扑排序看是否所有关系被唯一确定.即任意一次只能有1个元素入度为0入队. 1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <string> 5 #include <

CROC 2016 - Elimination Round Mischievous Mess Makers

这个题的意思是给你一个自然数序列1-n, 然后让你交换其中的一些数使得新序列的逆序对个数最大,  直接推公式即可, 代码如下: #include <bits/stdc++.h> using namespace std; typedef long long LL; int main() { int n, k; scanf("%d%d", &n, &k); LL pa = min(n/2, k); LL res1 = (n-2*pa)*pa; LL res2 =

VK Cup 2016 - Qualification Round 1 - D. Running with Obstacles

题意 : 在 x 坐标轴上,从 0 到 m 点,中途有 n 个障碍,遇到障碍可以 跳,但是每次跳之前需要一段 距离为 s 的“助跑 ”,而且每次跳跃距离不能超过 d ,不能落在障碍点上:给出 n,m,s,d,接下来 n 个数 ,表示障碍的坐标.输入保证起点和终点不会有障碍,不会有两个障碍在同一位置. 输出到达终点的过程.如果不能到达终点输出“IMPOSSIBLE” . 解题: 模拟啊模拟(好烦好烦= =) 首先 他一定是跑到距离障碍最近的位置才跳的,这样可以跳的更远些.然后两个障碍之间相距 要大

CROC 2016 - Elimination Round Enduring Exodus

这道题的意思是给你一串01序列, 0代表空房子, 1代表非空的房子, 农夫约翰和他的K个牛要住进空房子里面,i房子和j房子的距离是|j-i| 问农夫约翰和他的最远的牛的最小值是多少? 我们可以枚举牛的起点, 算出终点然后二分农夫约翰的位置, 代码如下: #include <bits/stdc++.h> using namespace std; int a[100000 + 100], na; int Binary(int num) { //找出<=num的最后一个位置 int l=0,