結果

問題 No.2976 高階多点評価
ユーザー ecotteaecottea
提出日時 2024-11-29 14:37:25
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
WA  
実行時間 -
コード長 2,561 bytes
コンパイル時間 10,142 ms
コンパイル使用メモリ 433,784 KB
実行使用メモリ 9,472 KB
最終ジャッジ日時 2024-11-29 14:37:48
合計ジャッジ時間 19,400 ms
ジャッジサーバーID
(参考情報)
judge2 / judge5
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 WA -
testcase_01 AC 15 ms
7,936 KB
testcase_02 RE -
testcase_03 AC 16 ms
8,192 KB
testcase_04 RE -
testcase_05 WA -
testcase_06 RE -
testcase_07 WA -
testcase_08 WA -
testcase_09 RE -
testcase_10 RE -
testcase_11 RE -
testcase_12 RE -
testcase_13 RE -
testcase_14 RE -
testcase_15 RE -
testcase_16 RE -
testcase_17 RE -
testcase_18 RE -
testcase_19 RE -
testcase_20 RE -
testcase_21 RE -
testcase_22 RE -
testcase_23 RE -
testcase_24 RE -
testcase_25 RE -
testcase_26 RE -
testcase_27 RE -
testcase_28 RE -
testcase_29 RE -
testcase_30 RE -
testcase_31 RE -
testcase_32 RE -
testcase_33 RE -
testcase_34 RE -
testcase_35 RE -
testcase_36 RE -
testcase_37 RE -
権限があれば一括ダウンロードができます

ソースコード

diff #

#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

#include <bits/stdc++.h>
using namespace std;

struct fast_io {
	fast_io() {
		cin.tie(nullptr);
		ios::sync_with_stdio(false);
		cout << fixed << setprecision(5);
	}
} fastIOtmp;

#include <boost/multiprecision/cpp_int.hpp>
using Bint = boost::multiprecision::cpp_int; 


int main() {
	// 係数列を前もって計算しておく.
	int N = 200;
	vector<vector<Bint>> f(N + 1);
	f[0] = vector<Bint>{ 1 };
	for (int n = 1; n <= N; ++n) {
		f[n].resize(n + 1);
		for (int i = 0; i < n; ++i) f[n][i + 1] -= 2 * n * f[n - 1][i];
		for (int i = 1; i < n; ++i) {
			f[n][i - 1] += i * f[n - 1][i];
			f[n][i + 1] += i * f[n - 1][i];
		}
		for (int i = 0; i < n; ++i) f[n][i] /= n;
	}

	vector<Bint> pow100000(N + 1);
	pow100000[0] = 1;
	for (int n = 0; n < N; ++n) pow100000[n + 1] = pow100000[n] * 100000;

	for (int n = 1; n <= N; ++n) for (int i = 0; i <= n; ++i) f[n][i] *= pow100000[n - i];

	int t;
	cin >> t;

	// クエリ先読み
	vector<long long> nXjs(t);
	for (int j = 0; j < t; ++j) {
		long long n; double x;
		cin >> n >> x;

		long long X_int((long long)(x * 100000 + (x > 0 ? 0.1 : -0.1)));

		nXjs[j] = (n << (18 + 17)) | (X_int << 17) | (long long)j;
	}

	// クエリの処理順をランダムにする.
	mt19937_64 mt(0);
	shuffle(nXjs.begin(), nXjs.end(), mt);

	vector<float> res(t);

	// 答えのメモ
	vector<map<int, float>> sol(201);

	for (auto nXj : nXjs) {
		int j = (int)(nXj & ((1LL << 17) - 1));
		nXj >>= 17;
		int X_int = (int)(nXj & ((1LL << 18) - 1));
		int n = (int)(nXj >> 18);
		
		if (n == 0) {
			res[j] = 1;
			continue;
		}

		// メモした答えの線形補間
		auto nit = sol[n].lower_bound(X_int);
		if (nit != sol[n].begin() && nit != sol[n].end()) {
			auto pit = prev(nit);

			auto [pi, pv] = *pit;
			auto [ni, nv] = *nit;

			// メモした答えの幅 40 以下の区間に挟まれているなら内挿補間する
			if (ni - pi <= 40) {
				float val = pv + (nv - pv) / (ni - pi) * (X_int - pi);
				res[j] = val;
				continue;
			}
		}

		Bint X = X_int;
		Bint X2 = X * X;

		// ここが遅い・・・はずなのだが思ってるよりずっと速い
		Bint Res = 0;
		for (int i = n; i >= 0; i -= 2) {
			Res *= X2;
			Res += f[n][i];
		}
		if (n & 1) Res *= X;

		float val = static_cast<float>(Res / pow100000[n - 1]);
		float x = X_int / 100000.f;
		val *= pow(x * x + 1, -n / 2.f) / 100000.f;

		res[j] = val;

		sol[n][X_int] = val;
	}

	for (int j = 0; j < t; ++j) cout << res[j] << "\n";
}
0