记录编号 617022 评测结果 AAAAAAAAAA
题目名称 3161.HS的自然数拆分 最终得分 100
用户昵称 Gravatarxuyuqing 是否通过 通过
代码语言 C++ 运行时间 4.741 s
提交时间 2026-07-02 19:48:26 内存使用 13.19 MiB
显示代码纯文本

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

const int N = 300010;
const int Len = 100000;
const long long Mod = 998244353;

int n;
int sqrtn;

int dp1[2][Len + 10];
long long dp1sum[N];

int dp2[Len + 10];
int sum[Len + 10];
long long dp2sum[N];

long long res[N];

template <typename T>
inline T my_pow (T a, T n) {
	T res = 1;
	while (n) {
		if (n & 1) {
			res = res * a % Mod;
		}
		a = a * a % Mod;
		n >>= 1;
	}
	return res % Mod;
}

namespace NTT {
	/*
	require:
		constant : N, Mod
		funcction : my_pow
		head file : algorithm
	*/
	
	const long long rt = 3;
	const long long rti = 332748118;
	long long cc = 0;
	long long limit = 1;
	long long change[N];
	
	void init_limit (const int & n, const int & m) {
		while (limit <= n + m) {
			limit <<= 1;
			cc++;
		}
	}
	
	void init_change () {
		for (int i = 0; i < limit; i++) {
			change[i] = (change[i >> 1] >> 1) | ((i & 1) << (cc - 1));
		}
	}
	
	void init_all (const int & n, const int & m) {
		init_limit (n, m);
		init_change ();
	}
	
	void ntt (long long nums[N], int flag) {
		for (int i = 0; i < limit; i++) {
			if (i < change[i]) {
				std::swap (nums[i], nums[change[i]]);
			}
		}
		
		for (long long mid = 1; mid < limit; mid <<= 1) {
			long long W = my_pow (((flag == 1) ? rt : rti), (Mod - 1) / (mid << 1));
			
			for (long long r = mid << 1, j = 0; j < limit; j += r) {
				long long w = 1;
				
				for (long long l = 0; l < mid; l++, w = w * W % Mod) {
					long long x = nums[j + l];
					long long y = w * nums[j + mid + l] % Mod;
	
					nums[j + l] = (x + y) % Mod;
					nums[j + mid + l] = (x - y + Mod) % Mod;
				}
			}
		}
	}
}

namespace PolynomialMultiplication {
	/*
	require:
		constant : N, Mod
		function : my_pow
		namespace : NTT
	*/
	
	void solve (long long one[N], int n, long long two[N], int m, long long res[N]) {
		NTT::init_all (n, m);
		NTT::ntt (one, 1);
		NTT::ntt (two, 1);
		
		for (int i = 0; i < NTT::limit; i++) {
			res[i] = one[i];
			res[i] *= two[i];
			res[i] %= Mod;
		}
		NTT::ntt (res, -1);
	
		long long inv = my_pow (NTT::limit, Mod - 2);
	
		for (int i = 0; i < n + m + 1; i++) {
			res[i] = res[i] * inv % Mod;
		}
	}
}

int main () {
	
	freopen ("zrscf.in", "r", stdin);
	freopen ("zrscf.out", "w", stdout);
	
	cin >> n;
	sqrtn = sqrt (Len);
	
	// > sqrtn
	dp1[0][0] = 1;
	dp1sum[0] = 1;
	int now = 0;
	for (long long i = 1; i * (sqrtn + 1) <= Len; i++) {
		now ^= 1;
		memset (dp1[now], 0, sizeof (dp1[now]));
		for (int j = i * (sqrtn + 1); j <= Len; j++) {
			dp1[now][j] = (dp1[now ^ 1][j - sqrtn - 1] + dp1[now][j - i]) % Mod;
			dp1sum[j] = (dp1sum[j] + dp1[now][j]) % Mod;
		}
	}
	
	// <= sqrtn
	dp2[0] = 1;
	sum[0] = 1;
	for (int i = 1; i <= sqrtn; i++) {
		for (int j = 0; j <= Len; j++) {
			sum[j] = dp2[j];
			if (j >= i) {
				sum[j] = (sum[j - i] + dp2[j]) % Mod;
			}
		}
		
		for (int j = i; j <= Len; j++) {
			dp2[j] = sum[j];
		}
		memset (sum, 0, sizeof (sum));
	}
	for (int i = 0; i <= Len; i++) {
		dp2sum[i] = dp2[i];
	}
	
	// all
	
	PolynomialMultiplication::solve (dp1sum, Len, dp2sum, Len, res);
	
	for (int i = 1; i <= n; i++) {
		int num;
		cin >> num;
		cout << res[num] - 1 << endl;
	}
	
	return 0;
}