P5516 [MtOI2019] 小铃的烦恼 题解
To_our_starry_sea · · 题解
Solution
这是一篇与其他题解有所不同的题解。最终并不需要使用高斯消元。
首先,问题可以转化为有
接着,设
显然对于每一次操作,对于钦定的颜色
-
该颜色数量增加,从
dp_{i - 1} 转移来,概率为\frac{i(s - i)}{s(s - 1)} 。 -
该颜色数量减少,从
dp_{i + 1} 转移来,概率为\frac{i(s - i)}{s(s - 1)} 。 -
该颜色数量不变,从
dp_{i} 转移来,概率为1 - \frac{2i(s - i)}{s(s - 1)} 。
综合以上可以得出下面的转移式:
注意到
考虑
将上式稍加变化即可得到:
带入之前的式子可得:
注意,接下来我们的方法便出现了不同。
类似对
也就是说我们得到了
考虑
当
然后线性递推即可。
注意到,更劣了。
Code
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2005;
int n, sum[MAXN];
char s[MAXN];
double dp[MAXN];
inline int read() {
int x = 0, f = 1; char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
return x * f;
}
int main() {
scanf("%s", s + 1);
n = strlen(s + 1);
int maxn = 0;
for (int i = 1; i <= n; i++) sum[s[i] - 'A' + 1]++, maxn = max(maxn, sum[s[i] - 'A' + 1]);
dp[1] = 1.0 * (n - 1) * (n - 1) / n, dp[2] = 2.0 * dp[1] - 1.0;
for (int i = 3; i <= maxn; i++) dp[i] = 2 * dp[i - 1] - dp[i - 2] - 1.0 * (n - 1) / (n - i + 1);
double ans = 0;
for (int i = 1; i <= 26; i++) ans += dp[sum[i]];
printf("%0.1lf\n", ans);
return 0;
}