求助煞笔卡精度题
查看原帖
求助煞笔卡精度题
421781
liuzimingc楼主2024/9/4 22:04

RT。对于 k≤8k \leq 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;
}
2024/9/4 22:04
加载中...