結果

問題 No.2976 高階多点評価
ユーザー ecottea
提出日時 2024-11-29 14:37:25
言語 C++17(gcc12)
(gcc 12.3.0 + boost 1.87.0)
結果
WA  
実行時間 -
コード長 2,561 bytes
コンパイル時間 29,622 ms
コンパイル使用メモリ 487,256 KB
最終ジャッジ日時 2025-02-25 06:30:20
ジャッジサーバーID
(参考情報)
judge3 / judge5
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
other AC * 2 WA * 4 RE * 24 TLE * 3 -- * 5
権限があれば一括ダウンロードができます

ソースコード

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