SDUT 2021 Autumn Team Contest 10th(补题)

Posted 佐鼬Jun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SDUT 2021 Autumn Team Contest 10th(补题)相关的知识,希望对你有一定的参考价值。

C - Justice

题目链接: link.

题意:

n n n个数,现在每个数都表示为 1 2 a i \\frac{1}{2^{a_i}} 2ai1,现在问你能否把 n n n个数拆分成2组,每组数的和必须 > = >= >= 1 2 \\frac{1}{2} 21,问能否把 n n n个数分成 2 2 2组满足题意,如果可以,并把划分2组的方案输出,用0和1来代表两个组

思路:

1 2 i \\frac{1}{2^i} 2i1 1 2 i \\frac{1}{2^i} 2i1= 1 2 i − 1 \\frac{1}{2^{i-1}} 2i11,也就是两个相同的数,可以合并成一个大数。此时划分方案,就是每个组里面至少有 1 1 1 1 1 1,也就是整个数组里面通过合并,是否至少有2个1,1可以是合并出来的,也可以是原有的,如果可以就是yes,否则就是no,再通过数组发现, n n n最大时1e5,在只有 n n n个数的情况下, a i a_i ai最小是1e5-1,也就是样例为1,2,3,4,……1e5-1,1e5-1,通过合并最后也是合法的,此时发现最大的数能用桶来存下,那么直接开个桶来记录每个数的个数,对于>1e5的数,就算有再多也对答案没影响,所以不做处理。通过不断合并看最后1的个数是否 > = 2 >=2 >=2,如果是,那就开始考虑方案,方案的话,就枚举对于当前这个数,需要多少个这样的数才能满足方案,记录下,这个数需要的个数,最后被标记个数的数为一组,剩下的数为一组。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e5;
int a[N + 10], cnt[N + 10], ans[N + 10];
int n;
ll qmi(ll a, ll k) {
    ll res = 1;
    while (k) {
        if (k & 1) res = res * a;
        k >>= 1;
        a = a * a;
    }
    return res;
}
void init() {
    memset(ans, 0, sizeof(ans));
    memset(cnt, 0, sizeof(cnt));
}
int main() {
    int T, idx = 1;
    scanf("%d", &T);
    while (T--) {
        init();
        scanf("%d", &n);
        int maxv = 0;
        for (int i = 0; i < n; i++) {
            scanf("%d", &a[i]);
            if (a[i] > N) continue;
            cnt[a[i]]++;
            maxv = max(maxv, a[i]);
        }
        ll p = 0;
        //计算1的个数
        for (int i = maxv; i > 1; i--) {
            p = (p + cnt[i]) / 2;
        }
        //1的个数>=2满足题意
        if (cnt[1] + p >= 2) {
            printf("Case %d: YES\\n", idx++);
            ll now = 0;
            //枚举当前这个数,在一组中需要多少个
            for (int i = 1; i <= maxv; i++) {
                ll temp = qmi(2, i - 1);
                if (cnt[i] + now >= temp) {
                    ans[i] = temp - now;
                    break;
                } else {
                    now = (now + cnt[i]) * 2;
                    ans[i] = cnt[i];
                }
            }
            for (int i = 0; i < n; i++) {
                if (a[i] > N)
                    printf("0");
                else {
                    if (ans[a[i]]) {
                        printf("1");
                        ans[a[i]]--;
                    } else
                        printf("0");
                }
            }
            printf("\\n");
        } else
            printf("Case %d: NO\\n", idx++);
    }
    return 0;
}

D - The Moon

题目链接: link.

题意:

有一个测试游戏的任务是拿到包裹,初始拿到包裹的概率是q=2% ,玩一局游戏获胜的概率是p,如果游戏获胜那就可以尝试拿包裹,成功拿包裹的概率是q,如果拿到就结束,没拿到就使得q=q+2%,并继续游戏。如果游戏失败,那就使q=q+1.5%,问拿到包裹的期望游戏回合数。

思路:

定义 f ( i ) f(i) f(i)为概率是 i i i的情况下,拿到包裹的期望回合数。
f ( i ) f(i) f(i)= p ∗ ( i + ( 1 − i ) ∗ [ f ( m i n ( 100 , i + 2 ) + 1 ] ) + ( 1 − p ) ∗ ( f ( m i n ( 100 , i + 1.5 ) + 1 ) p*(i+(1-i)*[f(min(100,i+2)+1])+(1-p)*(f(min(100,i+1.5)+1) p(i+(1i)[f(min(100,i+2)+1])+(1p)(f(min(100,i+1.5)+1)
代表含义就是 f ( i ) f(i) f(i)=当前获胜且拿到包裹的期望+获胜当前没拿到包裹的期望+没获胜后面拿到包裹的期望
为了防止1.5无法无法用整数表示所以,把所有数✖2
一开始f(200)即拿到包裹的概率是100%的情况下,能拿到包裹的期望就是 1 p \\frac{1}{p} p1,这就是经典硬币游戏的结论,引用过来就是,玩一个概率是p的游戏,赢了就结束,输了继续,结束的期望值是 1 p \\frac{1}{p} p1
m i n min min是为了防止越界

#include <bits/stdc++.h>
using namespace std;
const int N = 2000;
double f[N];

int main() {
    int T;
    scanf("%d", &T);
    int idx = 1;
    while (T--) {
        memset(f, 0, sizeof(f));
        printf("Case %d: ", idx++);
        double p;
        scanf("%lf", &p);
        p = p / 100.0;
        f[200] = 1.0 / p;
        for (int i = 199; i >= 4; i--) {
            double x = i / 200.0;
            f[i] = p * (x + (1 - x) * (f[min(i + 4, 200)] + 1)) + (1 - p) * (f[min(i + 3, 200)] + 1);
        }
        printf("%.10lf\\n", f[4]);
    }
    return 0;
}

To be continued
如果你有任何建议或者批评和补充,请留言指出,不胜感激

以上是关于SDUT 2021 Autumn Team Contest 10th(补题)的主要内容,如果未能解决你的问题,请参考以下文章

SDUT 2021 summer team contest 1st(for 20)(补题)

SDUT 2022 Winter Team Contest - 1

SDUT 2022 Winter Team Contest - 1

SDUT 2022 Winter Team Contest - 1

SDUT 2021 Spring Individual Contest(for 20) - 18(补题)

SDUT 2021 Summer Individual Contest - 2(for 20)(补题)