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;
}
浙公网安备 33010602011771号