省选测试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\n", 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\n", ans);
return 0;
}