Little Pony and Expected Maximum
题意
一个 m 面的骰子,投 n 次,求预期最大点数的期望值。
题解
首先,投掷的情况一共有 m n m^n mn种。
对于预期最大点数为 i (即 n 次中出现的最大点数是 i )的情况数为 i n − ( i − 1 ) n i^n-(i-1)^n in−(i−1)n
也就是都有点数都小于等于 i 的情况数减去都有点数都小于等于 (i - 1) 的情况数
因此,最后的期望为
∑ i = 1 m i ∗ ( i n − ( i − 1 ) n ) m n \frac{\sum_{i=1}^{m}i*(i^n-(i-1)^n)}{m^n} mn∑i=1mi∗(in−(i−1)n)
化简后可以得到
n − ∑ i = 1 m − 1 ( i n ) m ∗ i n-\sum_{i=1}^{m-1}(\frac{i}{n})^m*i n−∑i=1m−1(ni)m∗i
通过快速幂,线性求出 ( i n ) m (\frac{i}{n})^m (ni)m即可。
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const double eps = 1e-6;
double n, m;
double ksm(double a, ll b) {
double res = 1.0;
while (b) {
if (b & 1)res *= a;
b >>= 1;
a = a * a;
}
return res;
}
int main() {
cin >> m >> n;
double ans = m;
for (double i = 1; i <= m - 1; i++) {
ans -= ksm(i / m, n);
}
printf("%.10f", ans);
return 0;
}
Checkpoints
题意
有 n 个关卡,当该关卡为 1,他是一个关键点,为 0 则不是。
某人想要挑战这 n 个关卡,通过一个关卡的概率是1/2。
若在不是关键点的关卡挑战失败,需要回退到最近的且已经挑战成功的关键点。
已知期望挑战步数,构造符合期望步数的关卡。
题解
emmmmm…就很无语!
我手撸了一下样例,随便下了一个结论,看起来能过样例,就写了,就交了,然后过了,我人傻了。
“只要过了样例,都能交”
后来认真的分析了一下,结论确实是对的。
把一个连续的串1 0 0 0…当做一个关卡,对于 1 来说通过概率是 1/2,对于第 1 个 0 来说,需要通过 1 且通过当前关卡,那么通过概率是 1/4,因此对于第 i 个 0 来说,通过的概率是 1/2^(i+1)。
那么我们就可以知道,对于 1 来说,期望是 2 ,对于 0 来说,期望是 2^(i+1)。由于期望具有可加性,求和就是最后的期望步数。
所以,我们可以知道当期望为奇数时是无解的,偶数一定能构造出由 2^i 构成的数列。
预处理出 2^i 的前缀和,不停取小于等于当前剩余步数的pre 即可。
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int T;
ll n, pre[100];
void init() {
ll res = 2; pre[1] = res;
for (int i = 2; i <= 64; i++) pre[i] = res * 2 + pre[i - 1], res *= 2;
}
int main() {
init();
cin >> T;
while (T--) {
cin >> n;
if (n % 2 == 1)cout << "-1\n";
else {
ll ans = n, cnt = 0;
vector<int>vec;
while (ans > 0) {
int pos = lower_bound(pre + 1, pre + 1 + 63, ans) - pre;
if (pre[pos] == ans)vec.push_back(pos), ans = 0, cnt += pos;
else vec.push_back(pos - 1), ans -= pre[pos - 1], cnt += pos - 1;
}
cout << cnt << "\n";
for (auto x : vec) {
cout << 1 << ' ';
for (int i = 1; i < x; i++)cout << 0 << ' ';
}
cout << "\n";
}
}
return 0;
}