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;
}

T3 数点

T4 精shen细腻

posted @ 2025-07-15 21:08  Zctf1088  阅读(16)  评论(0)    收藏  举报