文章目录
3-Many Topological Problems
题意 问能构造多少序列 { a } i = 1 n \{a\}_{i=1}^n {a}i=1n 每个对应 n n n 个节点的树,使得 a p i < a i ≤ a p i + k a_{p_i}<a_i \leq a_{p_i} + k api<ai≤api+k,其中 p i p_i pi 为 i i i 的父节点
题解 对于每一种序列,其构造树的方式都是独立的,即序列的序号和权值两者并无关系,即可分开计算,最后乘法原理。
对于序列的序号来说,没有任何限制,即可任意搭配,排列组合可以构成 n ! n! n! 种序列
对于序列的权值来说,有 a p i < a i ≤ a p i + k a_{p_i}<a_i \leq a_{p_i} + k api<ai≤api+k,故按照点权从小到大插入点 i ( i > 1 ) i(i>1) i(i>1),有 m i n ( i − 1 , k ) min(i-1,k) min(i−1,k) 种方案,则一共 n ! ∏ i = 2 n m i n ( i − 1 , k ) n!\prod_{i=2}^nmin(i-1,k) n!∏i=2nmin(i−1,k) 种方案
- 当 n = k n=k n=k 时, r e s = n ! ( n − 1 ) ! res=n!(n-1)! res=n!(n−1)!
- 当 n ≠ k n\neq k n=k 时, r e s = n ! k ! k n − k − 1 res=n!k!k^{n-k-1} res=n!k!kn−k−1
对于阶乘可以先预处理
inline int qpow(int a, int b) {
int res = 1;
while (b) {
if (b & 1) res = (ll)res * a % mod;
a = (ll)a * a % mod;
b >>= 1;
}
return res;
}
int solve() {
int n, k; cin >> n >> k;
int res = 0;
if (n == k) res = (ll)fac[n] * fac[n - 1] % mod;
else res = (ll)fac[n] * fac[k] % mod * qpow(k, n - k - 1) % mod;
return res;
}
int main() {
fac[0] = 1;
for (int i = 1; i < N; i ++) fac[i] = (ll)fac[i - 1] * i % mod;
FastIO
Cases
cout << solve() << endl;
return 0;
}
4-Do You Like Interactive Problems?
题意 有一个未知数 x , x ∈ [ 1 , n ] x,x\in[1,n] x,x∈[1,n],每次随机询问一个数 y , y ∈ [ 1 , n ] y,y\in[1,n] y,y∈[1,n],会被告知 y y y 与 x x x 的大小关系( < , > , = <,>,= <,>,=),问知道 x x x 的询问次数的期望值
题解 可以打表,大概确定
// 打表 code
double solve(int n, int x) {
srand((int)time(0));
ll res = 0;
for (int i = 0; i < N; i ++) {
set<int> s;
int cnt = 0;
while (true) {
int y = rand() % n + 1;
s.insert(y);
if (s.count(x)) break;
if (x == 1) {
if (s.count(2)) break;
} else if (x == n) {
if (s.count(n - 1)) break;
} else {
if (s.count(x - 1) && s.count(x + 1)) break;
}
cnt ++;
}
res += cnt;
}
return (double)res / N;
}
打表结果
1 | 2 | 3 | 4 | 5 | 6 | … | 17 | 18 | … | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
50 | 23.042 | 32.135 | 32.063 | 33.659 | 31.525 | 31.217 | … | 32.559 | 33.496 | … | 32.194 | 33.28 | 23.592 | ||||||||||
51 | 24.631 | 33.873 | 33.5 | 31.252 | 31.252 | 31.494 | … | 33.697 | 33.776 | … | 34.81 | 32.896 | 31.802 | 25.459 | |||||||||
56 | 27.261 | 37.371 | 36.889 | 37.047 | 37.343 | 38.375 | … | 36.585 | 35.798 | … | 37.205 | 36.463 | 36.333 | 35.488 | 36.48 | 37.561 | 36.833 | 34.481 | 26.002 | ||||
57 | 27.999 | 38.345 | 38.648 | 37.54 | 36.678 | 37.229 | … | 36.502 | 35.608 | … | 36.755 | 35.884 | 36.235 | 35.752 | 36.576 | 36.447 | 37.459 | 38.021 | 37.233 | 27.147 | |||
58 | 29.613 | 38.708 | 39.247 | 38.129 | 37.209 | 36.357 | … | 39.021 | 37.833 | … | 36.68 | 37.998 | 36.402 | 36.402 | 36.853 | 36.468 | 37.412 | 36.69 | 37.718 | 38.254 | 29.669 | ||
59 | 27.141 | 37.798 | 37.474 | 37.945 | 38.964 | 38.895 | … | 40.325 | 39.722 | … | 37.705 | 38.908 | 39.344 | 36.964 | 38.409 | 38.084 | 37.215 | 36.896 | 36.533 | 36.634 | 37.857 | 29.267 | |
60 | 27.359 | 37.461 | 38.493 | 38.462 | 37.858 | 38.267 | … | 39.446 | 38.353 | … | 40.698 | 39.424 | 38.949 | 40.58 | 43.623 | 39.892 | 38.098 | 38.064 | 39.465 | 40.036 | 40.409 | 40.225 | 28.492 |
特判 n = 1 n=1 n=1 时,答案为 0 0 0
- x = 1 x=1 x=1 或 x = n x=n x=n 时,概率为 2 n \frac2n n2,期望为 1 2 n = n 2 \frac1{\frac2 n}=\frac n2 n21=2n
-
x
∈
[
2
,
n
−
1
]
x\in[2,n-1]
x∈[2,n−1] 时,要询问到点
x
x
x 或与其相邻的两个点,总期望为
E
1
=
1
n
⋅
0
+
2
n
⋅
n
2
+
n
−
3
n
⋅
E
1
+
1
E_1=\frac1n·0+\frac2n·\frac n2+\frac{n-3}n·E_1+1
E1=n1⋅0+n2⋅2n+nn−3⋅E1+1 解得
E
1
=
2
n
3
E_1=\frac{2n}3
E1=32n
- 询问到了点 x x x 或与其相邻的两个点,概率为 1 n \frac1n n1,步数为 0 0 0
- 只询问过了其中一个与 x x x 相邻的点,设期望为 E 2 E_2 E2,则 E 2 = 2 n ⋅ 0 + n − 2 n ⋅ E 2 + 1 E_2=\frac2n·0+\frac{n-2}n·E_2+1 E2=n2⋅0+nn−2⋅E2+1 解得 E 2 = n 2 E_2=\frac n2 E2=2n
- 没问到任何一个与 x x x 相邻的点,重新进入该循环,概率为 n − 3 n \frac{n-3}n nn−3,步数为 E 1 E_1 E1
综上,总期望为 E = 2 n ⋅ n 2 + n − 2 n ⋅ 2 n 3 = 2 n − 1 3 E=\frac2n·\frac n2+\frac{n-2}n·\frac{2n}3=\frac{2n-1}3 E=n2⋅2n+nn−2⋅32n=32n−1
const int mod = 998244353;
int inv3;
int qpow(int a, int b) {
int res = 1;
while (b) {
if (b & 1) res = (ll)res * a % mod;
a = (ll)a * a % mod;
b >>= 1;
}
return res;
}
int inv(int x) { return qpow(x, mod - 2); }
int solve() {
int n; cin >> n;
if (n == 1) return 0;
return (ll)(n * 2 - 1) * inv(3) % mod;
}
int main() {
inv3 = inv(3);
FastIO
Cases
cout << solve() << endl;
return 0;
}
12-Equalize the Array
题意 每次可以将数列里出现最多的数的所有这些数加一,求最终所有数能变成一样吗
题解 只要保证最小的数的数目为第一大即可(可以并列第一)
string solve() {
int n; cin >> n;
map<int, int> mp;
set<int> st;
for (int i = 0; i < n; i ++) {
int x; cin >> x;
st.insert(x);
mp[x] ++;
}
int cnt = mp[*s.begin()];
for (auto i : st)
if (mp[i] > cnt)
return no;
return yes;
}