比赛-训练赛 (15 Aug, 2018)

Posted ghcred

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了比赛-训练赛 (15 Aug, 2018)相关的知识,希望对你有一定的参考价值。

1.) 2357数

单调队列或者搜索都行。

#include <cstdio>
#include <deque>

using namespace std;

typedef long long ll;

deque<ll> A[4];

int main()
{
    ll N, x;
    scanf("%lld", &N);
    x = 1;
    while (x < N) {
        A[0].push_back(x * 2);
        A[1].push_back(x * 3);
        A[2].push_back(x * 5);
        A[3].push_back(x * 7);
        int p = 0;
        for (int i = 1; i <= 3; ++i) {
            if (A[i].front() < A[p].front())
                p = i;
        }
        x = A[p].front();
        for (int i = 0; i <= 3; ++i) {
            if (A[i].front() == A[p].front())
                A[i].pop_front();
        }
    }
    printf("%lld
", x);
    return 0;
}

2.) 监狱

区间 DP 。枚举区间内第一个被释放的人来转移状态。

#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

const int INF = 1e9;
const int _N = 200;

int A[_N], B[15], f[_N][_N], N, M, ans;
bool mk[_N];

void test()
{
    int cnt = 0;
    for (int i = 1; i <= N; ++i)
        mk[i] = 0;
    for (int i = 1; i <= M; ++i) {
        int j;
        mk[A[B[i]]] = 1;
        for (j = A[B[i]] - 1; j >= 1 && !mk[j]; --j);
        cnt += A[B[i]] - 1 - j;
        for (j = A[B[i]] + 1; j <= N && !mk[j]; ++j);
        cnt += j - 1 - A[B[i]];
    }
    ans = min(ans, cnt);
    return;
}

void fun1()
{
    for (int i = 1; i <= M; ++i)
        B[i] = i;
    ans = INF;
    test();
    while (next_permutation(B + 1, B + 1 + M))
        test();
    printf("%d
", ans);
    return;
}

int dfs(int l, int r)
{
    if (f[l][r] != -1) {
        return f[l][r];
    }
    if (l == r) {
        return f[l][r] = 0;
    }
    f[l][r] = INF;
    for (int i = l; i <= r; ++i) {
        f[l][r] = min(f[l][r], dfs(l, i) + dfs(i + 1, r) + A[r] - A[l - 1] - 2);
    }
//  printf("[%d, %d] = %d
", l, r, f[l][r]);
    return f[l][r];
}

int main()
{
    
    scanf("%d%d", &N, &M);
    for (int i = 1; i <= M; ++i) {
        scanf("%d", &A[i]);
    }
    if (N <= 105 && M <= 6) {
        fun1();//O(M! * N * M)
        return 0;
    }
    sort(A + 1, A + 1 + M);
    A[0] = 0, A[M + 1] = N + 1;
    memset(f, -1, sizeof f);
    printf("%d
", dfs(1, M + 1));
    return 0;
}

3.) lucknum

数位 DP 可以拿到 60 分。注意到 DP 方程和组合数的递推式很像。考虑把 (n) 个数位作为球,把这些球扔到 (m) 表示 ([0, m-1])(m) 个数字的桶里去(或分成 (m) 份)。扔完后按桶表示的数字大小从小到大排序,把扔到桶内的球对应的数位上的数,设置为桶表示的数字,就得到了一个合理的 lucknum 。桶内可以为空。隔板法搞一下答案就是 (left(_{m-1}^{n+m-1} ight))

#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

typedef long long ll;

ll N, M, P;

ll mont(ll t1, ll t2)
{
    t1 %= P;
    ll t = 1;
    while (t2) {
        if (t2 & 1)
            t = t * t1 % P;
        t2 >>= 1;
        t1 = t1 * t1 % P;
    }
    return t;
}

int main()
{
    ll dn, up;
    scanf("%lld%lld%lld", &N, &M, &P);
    dn = M + N - 1;
    up = M - 1;
    if (up > dn - up)
        up = dn - up;
    ll t0 = 1, t1 = 1;
    for (ll i = 1; i <= up; ++i) {
        t0 = t0 * i % P;
        t1 = t1 * (dn - i + 1) % P;
    }
    printf("%lld
", t1 * mont(t0, P - 2) % P);
    return 0;
}

以上是关于比赛-训练赛 (15 Aug, 2018)的主要内容,如果未能解决你的问题,请参考以下文章

比赛-thh学长的训练赛2 (20 Aug, 2018)

比赛-thh学长的训练赛 (Aug 16, 2018)

比赛-OBlack学长的训练赛 (25 Aug, 2018)

比赛-暑假训练赛1 (26 Jul, 2018)

2018-2019赛季多校联合新生训练赛第六场(2018/12/15)补题题解

郑州大学2018新生训练赛第十场题解