题意 问能构造多少序列 { 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}
题解 对于每一种序列,其构造树的方式都是独立的,即序列的序号和权值两者并无关系,即可分开计算,最后乘法原理。
对于序列的序号来说,没有任何限制,即可任意搭配,排列组合可以构成 n ! n! n! 种序列
对于序列的权值来说,有 a p i < a i ≤ a p i + k a_{p_i}
对于阶乘可以先预处理
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;
}
题意 有一个未知数 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
综上,总期望为 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;
}
题意 每次可以将数列里出现最多的数的所有这些数加一,求最终所有数能变成一样吗
题解 只要保证最小的数的数目为第一大即可(可以并列第一)
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;
}