2025CSP-S模拟赛15 比赛总结
2025CSP-S模拟赛15
T1 万花筒
这个题其实考试时想得差不多了。
简单写了。将边从小到大排序。令 \(d=|u-v|\),那么加入这些边(即 \((u+k,v+k)\))后,会产生 \(\gcd(m,d)\) 个连通块,其中 \(m\) 为加入这些边前连通块的数量。当连通块总数为 1 时输出总代价,然后就没了。
#include <bits/stdc++.h>
#define int long long
using namespace std;
int read() {
int x = 0; char ch = getchar();
while (ch < '0' || ch > '9') ch = getchar();
while (ch >= '0' && ch <= '9') {
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return x;
}
const int INF = 0x3f3f3f3f3f3f3f3f;
const int N = 1e9 + 10, M = 1e5 + 10;
int n, m;
struct node {
int x, y, w;
bool operator < (const node & cmp) const {
return w < cmp.w;
}
} e[M];
int d[M], w[M];
int gcd(int n, int m) {
return m == 0 ? n : gcd(m, n % m);
}
int solve() {
n = read(), m = read();
for (int i = 1; i <= m; i++) {
e[i] = {read(), read(), read()};
}
sort(e + 1, e + 1 + m);
int ans = 0;
for (int i = 1; i <= m; i++) {
int d = abs(e[i].x - e[i].y);
int num = n - gcd(n, d);
if (num > 0) {
ans += num * e[i].w;
n = gcd(n, d);
}
}
printf("%lld\n", ans);
return 0;
}
signed main() {
int qq = read();
while (qq--) {
solve();
}
return 0;
}
T2 冒泡排序趟数期望
考虑对于排列 \(p[i]\),定义 \(inv[i]=\sum[j<i \and p[j]>p[i]]\),不难得出 \(res=\max inv[i]\)。
然后我们可以发现,\(inv[i] \in [0,i-1]\),所以不同的 \(inv\) 数组共有 \(n!\) 个,恰好和所有排列一一对应。依此,问题可以转化为求 \(\max inv[i]=k\) 的方案数。
考虑构造合法的 \(inv\) 数组。要使构造的 \(inv\) 最大值为 \(k\),则:对于 \(i \le k\) 的位置随便取,\(i>k\) 的位置 \(<k\) 且至少有一个 \(k\)。方案数即为:
\[cnt[k]=k!((k+1)^{n-k}-k^{n-k})
\]
答案即为 \(\frac{\sum k\times cnt[k]}{n!}\)。
#include <bits/stdc++.h>
#define int long long
using namespace std;
int read() {
int x = 0; char ch = getchar();
while (ch < '0' || ch > '9') ch = getchar();
while (ch >= '0' && ch <= '9') {
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return x;
}
const int MOD = 1e9 + 7;
const int N = 1e6 + 10;
int n, fact[N];
int fpow(int a, int x) {
a %= MOD;
int ans = 1;
while (x) {
if (x & 1) ans = ans * a % MOD;
a = a * a % MOD;
x >>= 1;
}
return ans;
}
int ans = 0;
int a[N];
signed main() {
n = read();
fact[0] = 1;
for (int i = 1; i <= n; i++) fact[i] = fact[i - 1] * i % MOD;
int ans = 0;
for (int i = 0; i < n; i++) {
ans = (ans + (fact[i] * (fpow(i + 1, n - i) - fpow(i, n - i) + MOD) % MOD) % MOD * i % MOD) % MOD;
}
ans = ans * fpow(fact[n], MOD - 2) % MOD;
printf("%lld\n", ans);
return 0;
}

浙公网安备 33010602011771号