0727 模拟赛

A

被拉爆了,考试的时候没有弄懂题意。

给定一个数 \(u, v\)。可以构造一个大小为 \(2 \times (2u + v)\) 的图,其中初始 \(i~(1 \le i \le 2u + v)\) 与 \(i + 2u + v\) 有无向边。现在每个点有其颜色:对于编号 \([1, u], [2u + v + 1, 3u + 2v]\) 的点涂成绯色,其余涂成青色。现在要额外建 \(2u + v\) 个无向边(可以与之前的重合),满足:

  • 每条边连接两个颜色不同的点
  • 每个点有且仅有一个额外的边与它相连

求最后整个图是联通图的期望。

\(1 \le u, v \le 10^6\)

若设 \(H_i = 1 + \frac{1}{2} + \frac{1}{3} + \dots + \frac{1}{i}\)(调和级数)。

则不难发现答案为 \(H_{2u + v} - \frac{1}{2}H_{u}\)。(这只需要较强的思维发散能力和惊人的注意力。证明需要高中知识,我不懂)

贴
#include <cstdio>
#include <random>
#include <ctime>
using namespace std;
mt19937 rnd (time (NULL));
#define rand(x,y) rnd() % (x + y - 1) + x

long double h[3000010];
int n, m;

int main () {
    freopen ("weave.in", "r", stdin);
    freopen ("weave.out", "w", stdout);
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= 2 * n + m; i ++) {
        h[i] = h[i - 1] + 1.0 / i;
    }
    printf("%.10Lf", h[2 * n + m] - h[n] / 2.0);
    return 0;
}

B

现有两个字符串 \(s, t\),长度相等。你需要构造一个序列 \(i_1, i_2, \dots, i_n~(1 \le i_1 < i_2 < \dots < i_n < |s|)\) 使得字符串 \(s_{i_1}s_{i_2}\dots s_{i_n}t_{i_1}t_{i_2}\dots t_{i_n}\) 字典序最大。

\(|s| \le 50\)

注意到 \(|s|\) 很小,肯定不是贪心,故 dp

设 \(\texttt{dp}_{i, j}\) 表示遍历到第 \(i\) 位,已经选了 \(j\) 个下标的字典序最大的方案(存一个状态,表示第 \(i\) 位有没有选)。

那么易有转移,是选这一位和不选这一位两种可能。

贴
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

typedef long long ll;
const int N = 60;
ll dp[N][N];
int n;
char s[N], t[N];

ll chs (ll x, ll y) {
    int a[N], b[N], now = 0, noww = 0;
    ll xx = x, yy = y;
    int i = 0;
    while (xx > 0) {
        i ++;
        if (xx & 1) a[++ now] = i;
        xx >>= 1;
    } i = 0; while (yy > 0) {
        i ++;
        if (yy & 1) b[++ noww] = i;
        yy >>= 1;
    } int l = 1, r = 1;
    // printf("\n%lld vs %lld\n", x, y);
    // for (int i = 1; i <= now; i ++) printf("(%d)", a[i]);
    // for (int i = 1; i <= noww; i ++) printf("[%d]", b[i]);
    while (l <= 2 * now && r <= 2 * noww) {
        char sb, sbb;
        if (l <= now) sb = s[a[l]];
        else sb = t[a[l - now]];
        if (r <= noww) sbb = s[b[r]];
        else sbb = t[b[r - noww]];
        // printf("%d %d %c %c\n", l, r, sb, sbb);
        if (sb > sbb) {
            // printf("A");
            return x;
        } else if (sb < sbb) {
            // printf("B");
            return y;
        }
        l ++, r ++;
    } 
    // printf("(%d %d)", l, r);
    if (r <= 2 * noww) {
        // printf("B");
        return y;}
    // printf("A");
    return x;
}

int main () {
    freopen ("cipher.in", "r", stdin);
    freopen ("cipher.out", "w", stdout);
    scanf("%s%s", s + 1, t + 1);
    n = strlen (s + 1);
    for (int i = 1; i <= n; i ++) {
        for (int j = 1; j <= n; j ++) {
            dp[i][j] = chs (dp[i][j], dp[i - 1][j - 1] + (1ll << (i - 1)));
            dp[i][j] = chs (dp[i][j], dp[i - 1][j]);
        }
    }
    int a[N], now = 0, i = 0;
    ll x = 0;
    for (int j = 1; j <= n; j ++) {
        x = chs (x, dp[n][j]);
    }
    // printf("%lld\n", x);
    while (x) {
        i ++;
        if (x & 1) a[++ now] = i;
        x >>= 1;
    }
    for (int i = 1; i <= now; i ++) {
        printf("%c", s[a[i]]);
    } for (int i = 1; i <= now; i ++) {
        printf("%c", t[a[i]]);
    } printf("\n");
    return 0;
}
posted on 2026-07-27 16:18  Zhaoxiyan  阅读(6)  评论(0)    收藏  举报