省选测试21

县里让做核酸检测,做的时候到挺快,排队排了一上午,又没交

A Skip

题目大意 : 参加比赛可以获得一定的愉悦值,连续不参见会减少,求能获得的最大愉悦值

  • 很容易想到dp,f[i]表示参加第i场比赛可以获得的最大愉悦值,利用决策单调性,用cdq来做

Code

Show Code
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
typedef long long L;
const int N = 1e5 + 5;

int read(int x = 0, int f = 1, char c = getchar()) {
    for (; c < '0' || c > '9'; c = getchar()) if (c == '-') f = -1;
    for (; c >='0' && c <='9'; c = getchar()) x = x * 10 + c - '0';
    return x * f;
}

L f[N];
int n, a[N], p[N], q[N];

bool Cmp(int x, int y) {
    return a[x] != a[y] ? a[x] < a[y] : x < y;
}

L F(int x) {
    return 1ll * x * (x - 1) / 2;
}

double Cal(int x, int y) {
    return (double) (f[y] - f[x] - F(y+1) + F(x+1)) / (x - y);
}

void Solve(int L, int R) {
    if (L == R) return;
    int mid = L + R >> 1, l = 1, r = 0;
    Solve(L, mid);
    sort(p + L, p + mid + 1);
    sort(p + mid + 1, p + R + 1);
    for (int i = L, j = mid + 1; j <= R; ++j) {
        for (; i <= mid && p[i] < p[j]; ++i) {
            while (l < r && Cal(q[r-1], q[r]) >= Cal(q[r], p[i])) r--;
            q[++r] = p[i];
        }
        while (l < r && f[q[l]] + a[p[j]] - F(p[j] - q[l]) <= f[q[l+1]] + a[p[j]] - F(p[j] - q[l+1])) l++;
        if (l <= r) f[p[j]] = max(f[p[j]], f[q[l]] + a[p[j]] - F(p[j] - q[l]));
    }
    sort(p + L, p + R + 1, Cmp);
    Solve(mid + 1, R);
}

int main() {
    n = read() + 1;
    for (int i = 1; i < n; ++i) 
        a[i] = read();
    memset(f + 1, 0xcf, n * 8);
    a[0] = -2e9; a[n] = 2e9;
    for (int i = 1; i <= n; ++i)
        p[i] = i;
    sort(p + 1, p + n + 1, Cmp);
    Solve(0, n);
    printf("%lld
", f[n] - a[n]);
    return 0;
}

B String (Unaccepted)

题目大意 :

  • 咕咕

Code

Show Code

C Permutation

题目大意 : 从1~n中选出k个能组成所有序列(从小到大排序)按字典序排序后相邻序列各位置差的绝对值

  • 相邻的序列从第一个不相同的位置开始,前一个是最后几个,后一个是前面几个然后组合数就好了

Code

Show Code
#include <cstdio>

using namespace std;
const int N = 2e6 + 5, M = 1e9 + 7;

int n, k, m, fac[N], fai[N], ans;

int Pow(int a, int k, int ans = 1) {
    for (; k; k >>= 1, a = 1ll * a * a % M)
        if (k & 1) ans = 1ll * ans * a % M;
    return ans;
}

void Pre(int n) {
    fac[0] = 1;
    for (int i = 1; i <= n; ++i)
        fac[i] = 1ll * fac[i-1] * i % M;
    fai[n] = Pow(fac[n], M - 2);
    for (int i = n; i >= 1; --i)
        fai[i-1] = 1ll * fai[i] * i % M;
}

int C(int n, int m) {
    return 1ll * fac[n] * fai[m] % M * fai[n-m] % M;
}

int main() {
    scanf("%d%d%d", &n, &k, &m);
    if (n == k) return puts("0"), 0;
    n -= k + 1; Pre(n + m);
    if (m >= 2) {
        for (int i = 0; i <= n; ++i)
            if ((ans += 1ll * (n - i) * C(m-1+i, m-2) % M) >= M) ans -= M;
    }
    for (int i = 0; i <= n; ++i)
        if ((ans += C(m-1+i, m-1)) >= M) ans -= M;
    printf("%d
", ans);
    return 0;
}
原文地址:https://www.cnblogs.com/shawk/p/14413745.html