結果

問題 No.980 Fibonacci Convolution Hard
ユーザー QCFiumQCFium
提出日時 2020-04-15 22:14:49
言語 C++14
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 1,772 ms / 2,000 ms
コード長 3,052 bytes
コンパイル時間 1,970 ms
コンパイル使用メモリ 180,304 KB
実行使用メモリ 193,432 KB
最終ジャッジ日時 2024-10-01 19:05:22
合計ジャッジ時間 35,316 ms
ジャッジサーバーID
(参考情報)
judge1 / judge5
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1,741 ms
193,300 KB
testcase_01 AC 1,708 ms
193,172 KB
testcase_02 AC 1,671 ms
193,144 KB
testcase_03 AC 1,763 ms
193,300 KB
testcase_04 AC 1,720 ms
193,304 KB
testcase_05 AC 1,733 ms
193,304 KB
testcase_06 AC 1,743 ms
193,304 KB
testcase_07 AC 1,498 ms
193,296 KB
testcase_08 AC 1,575 ms
193,176 KB
testcase_09 AC 1,514 ms
193,300 KB
testcase_10 AC 1,581 ms
193,172 KB
testcase_11 AC 1,701 ms
193,304 KB
testcase_12 AC 1,661 ms
193,296 KB
testcase_13 AC 1,602 ms
193,176 KB
testcase_14 AC 1,659 ms
193,260 KB
testcase_15 AC 1,772 ms
193,432 KB
testcase_16 AC 1,568 ms
193,300 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>

int ri() {
	int n;
	scanf("%d", &n);
	return n;
}

template<int mod, int proot> struct NTT {
	int get_mod() { return mod; }
	int pow(int a, int b) {
	int res = 1;
		for (; b; b >>= 1) {
			if (b & 1) res = (int64_t) res * a % mod;
			a = (int64_t) a * a % mod;
		}
		return res;
	}
	int inv(int i) { return pow(i, mod - 2); }
	void ntt(std::vector<int> &a, bool inverse) {
		int n = a.size();
		assert((n & -n) == n);
		int h = pow(proot, (mod - 1) / n);
		if (inverse) h = inv(h);
		
		for (int i = 0, j = 1; j < n - 1; j++) {
			for (int k = n >> 1; k > (i ^= k); k >>= 1);
			if (j < i) std::swap(a[i], a[j]);
		}
		for (int i = 1; i < n; i <<= 1) {
			int base = pow(h, n / i / 2);
			int w = 1;
			
			std::vector<int> ws(i);
			for (int j = 0; j < i; j++) ws[j] = w, w = (int64_t) w * base % mod;
			
			for (int j = 0; j < n; j += i << 1) {
				for (int k = 0; k < i; k++) {
					int u = a[k + j];
					int d = (int64_t) a[k + j + i] * ws[k] % mod;
					a[k + j] = u + d >= mod ? u + d - mod : u + d;
					a[k + j + i] = d > u ? u + mod - d : u - d;
				}
			}
		}
		if (inverse) {
			int ninv = inv(a.size());
			for (auto &i : a) i = (int64_t) i * ninv % mod;
		}
	}
	std::vector<int> conv_same(const std::vector<int> a_) {
		std::vector<int> a = a_;
		size_t size = 1;
		for (; size < a_.size() + a_.size(); size <<= 1);
		a.resize(size);
		ntt(a, false);
		for (size_t i = 0; i < size; i++) a[i] = (int64_t) a[i] * a[i] % mod;
		ntt(a, true);
		a.resize(a_.size() + a_.size() - 1);
		return a;
	}
};

template<int mod>
int64_t inv(int64_t a) {
	a %= mod;
	int res = 1;
	for (int x = mod - 2; x; x >>= 1) {
		if (x & 1) res = (int64_t) res * a % mod;
		a = (int64_t) a * a % mod;
	}
	return res;
}

#define MOD 1000000007
// copied from https://math314.hateblo.jp/entry/2015/05/07/014908
std::vector<int64_t> conv_mod(std::vector<int> a){
	NTT<935329793, 3> ntt1;
	NTT<943718401, 7> ntt2;
	NTT<998244353, 3> ntt3;
	auto x_ = ntt1.conv_same(a);
	auto y_ = ntt2.conv_same(a);
	auto z_ = ntt3.conv_same(a);
	std::vector<int64_t> x, y, z;
	for (auto i : x_) x.push_back(i);
	for (auto i : y_) y.push_back(i);
	for (auto i : z_) z.push_back(i);
	
	constexpr int64_t m1 = 935329793, m2 = 943718401, m3 = 998244353;
	const int64_t m1_inv_m2 = inv<m2>(m1);
	const int64_t m12_inv_m3 = inv<m3>(m1 * m2);
	const int64_t m12_mod = m1 * m2 % MOD;
	std::vector<int64_t> ret(x.size());
	for (int i = 0; i < (int) x.size(); i++) {
		int64_t v1 = (y[i] - x[i]) * m1_inv_m2 % m2;
		if (v1 < 0) v1 += m2;
		int64_t v2 = (z[i] - (x[i] + m1 * v1) % m3) * m12_inv_m3 % m3;
		if (v2 < 0) v2 += m3;
		int64_t constants3 = (x[i] + m1 * v1 + m12_mod * v2) % MOD;
		if (constants3 < 0) constants3 += MOD;
		ret[i] = constants3;
	}

	return ret;
}

int main() {
	int p = ri();
	std::vector<int> a(2000001);
	a[1] = 0;
	a[2] = 1;
	for (int i = 3; i <= 2000000; i++) a[i] = ((int64_t) a[i - 1] * p + a[i - 2]) % MOD;
	
	auto res = conv_mod(a);
	
	int q = ri();
	for (int i = 0; i < q; i++) {
		printf("%d\n", (int) res[ri()]);
	}
  	return 0;
}
0