RT。对于 k≤8 的部分使用 long double,写在 namespace sol1 里然后 WA 掉了。反而是 __float128 的没事,求助:
#include <bits/stdc++.h>
using namespace std;
namespace liuzimingc {
#define endl '\n'
#define ld long double
#define _f __float128
const int N = 105, M = 35, MOD = 1e9 + 7;
int n, l, k, a[N];
namespace sol1 {
ld f[N][N][M][3];
ld ans;
void add(ld &x, ld y) { x += y; }
void print(ld ans) {
if (ans + 1e-14 >= 1) {
cout << "1.";
for (int i = 1; i <= k; i++) cout << 0;
return;
}
cout << "0.";
ans *= 10;
for (int i = 1; i <= k; i++) {
cout << int(ans + (k == i) * 0.5);
ans = ans - int(ans);
ans *= 10;
}
}
int main() {
f[0][0][0][0] = 1;
for (int i = 0; i < n; i++)
for (int j = 0; j <= i; j++)
for (int k = 0; k <= l; k++)
for (int d = 0; d <= 2; d++) {
int nk = k + (2 * j - d);
f[i][j][k][d] /= i + 1;
ld now = f[i][j][k][d];
if (nk > l) continue;
if (j >= 2) add(f[i + 1][j - 1][nk][d], now * (j - 1)); // 合并
add(f[i + 1][j + 1][nk][d], now * (j + 1 - d)); // 段插入,不为边界的空隙中
if (d < 2) add(f[i + 1][j + 1][nk][d + 1], now * (2 - d)); // 段插入,作为边界
if (j >= 1) add(f[i + 1][j][nk][d], now * (2 * j - d));// 元素插入,段中间
if (d < 2 && j >= 1) add(f[i + 1][j][nk][d + 1], now * (2 - d));// 元素插入,作为段边界
}
ld ans = 0;
for (int i = 0; i <= l; i++) add(ans, f[n][1][i][2]);
print(1 - ans);
return 0;
}
}
namespace sol2 {
_f f[N][N][M][3];
_f ans;
void add(_f &x, _f y) { x += y; }
void print(_f ans) {
if (ans + 1e-14 >= 1) {
cout << "1.";
for (int i = 1; i <= k; i++) cout << 0;
return;
}
cout << "0.";
ans *= 10;
for (int i = 1; i <= k; i++) {
cout << int(ans + (k == i) * 0.5);
ans = ans - int(ans);
ans *= 10;
}
}
int main() {
f[0][0][0][0] = 1;
for (int i = 0; i < n; i++)
for (int j = 0; j <= i; j++)
for (int k = 0; k <= l; k++)
for (int d = 0; d <= 2; d++) {
int nk = k + (2 * j - d);
f[i][j][k][d] /= i + 1;
_f now = f[i][j][k][d];
if (nk > l) continue;
if (j >= 2) add(f[i + 1][j - 1][nk][d], now * (j - 1)); // 合并
add(f[i + 1][j + 1][nk][d], now * (j + 1 - d)); // 段插入,不为边界的空隙中
if (d < 2) add(f[i + 1][j + 1][nk][d + 1], now * (2 - d)); // 段插入,作为边界
if (j >= 1) add(f[i + 1][j][nk][d], now * (2 * j - d));// 元素插入,段中间
if (d < 2 && j >= 1) add(f[i + 1][j][nk][d + 1], now * (2 - d));// 元素插入,作为段边界
}
_f ans = 0;
for (int i = 0; i <= l; i++) add(ans, f[n][1][i][2]);
print(1 - ans);
return 0;
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n >> l >> k;
if (!l) {
cout << "1.";
for (int i = 1; i <= k; i++) cout << 0;
return 0;
}
l--;
if (false) sol1::main();
else sol2::main();
return 0;
}
} // namespace liuzimingc
int main() {
liuzimingc::main();
return 0;
}