結果
問題 | No.2164 Equal Balls |
ユーザー |
![]() |
提出日時 | 2022-12-17 12:26:51 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 4,884 ms / 5,000 ms |
コード長 | 5,265 bytes |
コンパイル時間 | 1,191 ms |
コンパイル使用メモリ | 91,312 KB |
最終ジャッジ日時 | 2025-02-09 15:06:14 |
ジャッジサーバーID (参考情報) |
judge5 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 51 |
コンパイルメッセージ
main.cpp: In function ‘int main()’: main.cpp:131:20: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 131 | int n, m; scanf("%d %d", &n, &m); | ~~~~~^~~~~~~~~~~~~~~~~ main.cpp:133:38: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 133 | for (int i = 0; i < n; i++) scanf(" %d", &a[i]); | ~~~~~^~~~~~~~~~~~~~ main.cpp:134:38: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 134 | for (int i = 0; i < n; i++) scanf(" %d", &b[i]); | ~~~~~^~~~~~~~~~~~~~
ソースコード
#include <array>#include <cstdio>#include <cmath>#include <cassert>#include <vector>#include <iostream>using namespace std;template<int mod>class modint {int val = 0;constexpr static int normalize(long long x) {if (0 <= x and x < mod) return static_cast<int>(x);else { x %= mod; return static_cast<int>(x >= 0 ? x : x + mod); }}public:static const int modulus = mod;modint() {}constexpr modint(long long n) : val(normalize(n)) {}constexpr int value() const { return val; }constexpr modint operator-() const { return modint(mod - val); }constexpr modint inverse() const {long long x = mod, y = val, p = 1, q = 0, r = 0, s = 1;while (y != 0) {long long u = x / y;long long x0 = y; y = x - y * u; x = x0;long long r0 = p - r * u, s0 = q - s * u;p = r; r = r0; q = s; s = s0;}return modint(q);}constexpr const modint pow(long long e) const {if (e < 0) return pow(-e).inverse();long long ans = 1, p = val;while (e > 0) {if (e % 2 != 0) ans = (ans * p) % mod;p = (p * p) % mod;e >>= 1;}return modint(ans);}constexpr modint &operator+=(const modint r) {val += r.value();if (val >= mod) val -= mod;return *this;}constexpr modint &operator-=(const modint r) {val -= r.value();if (val < 0) val += mod;return *this;}constexpr modint &operator*=(const modint r) {val = (long long)val * r.value() % mod;return *this;}constexpr modint &operator/=(const modint r) {if (r.value() == 2) {val = (val % 2 ? val + mod : val) / 2;} else {val = (long long)val * r.inverse().value() % mod;}return *this;}friend constexpr modint operator+(const modint l, const modint r) {const int newval = l.value() + r.value();return newval >= mod ? newval - mod : newval;}friend constexpr modint operator-(const modint l, const modint r) { return l + (- r); }friend constexpr modint operator*(const modint l, const modint r) { return (long long)l.value() * r.value(); }friend constexpr modint operator/(const modint l, const modint r) { return l * r.inverse(); }friend constexpr bool operator==(const modint l, const modint r) { return l.value() == r.value(); }friend constexpr bool operator!=(const modint l, const modint r) { return l.value() != r.value(); }};constexpr int M = 998244353;using mint = modint<M>;namespace NTT {template<typename T>constexpr bool is_primitive_root(int i) {constexpr int p = T::modulus;int d = 2, r = p - 1;while ((long long)d * d <= r) {if (r % d == 0) {if (T(i).pow((p - 1) / d).value() == 1) return false;do { r /= d; } while (r % d == 0);}d++;}if (r > 1 and T(i).pow((p - 1) / r).value() == 1) return false;return true;}template<typename T>constexpr T primitive_root() {constexpr int p = T::modulus;for (int i = 2; i < p; i++) if (is_primitive_root<T>(i)) return i;return 0;}template<typename T>void ntt(vector<T> &a, bool inv) {constexpr int p = T::modulus;constexpr T r = primitive_root<T>();const int n = int(a.size());assert((p - 1) % n == 0);const int expn = (p - 1) / n * (inv ? -1 : 1);const T zn = r.pow(expn);auto b = a;for (int step = n / 2; step > 0; step /= 2) {const T wn = zn.pow(step);T w = 1;for (int t = 0, tmax = n / step / 2; t < tmax; t++) {for (int offset = 0; offset < step; offset++) {const int i = offset + step * t, j = i + step * t;assert(j + step < n);const T x = a[j], y = w * a[j + step];b[i] = x + y;b[i + n/2] = x - y;}w *= wn;}if (inv) for (int i = 0; i < n; i++) b[i] /= 2;swap(a, b);}}};int main() {int n, m; scanf("%d %d", &n, &m);vector<int> a(n), b(n);for (int i = 0; i < n; i++) scanf(" %d", &a[i]);for (int i = 0; i < n; i++) scanf(" %d", &b[i]);vector<mint> q1(1 << 17, 1), q2(1 << 17, 1);array<array<mint, 601>, 601> comb;for (int i = 0; i < 601; ++i)for (int j = 0; j < 601; ++j)if (j == 0) comb[i][j] = 1;else if (i == 0) comb[i][j] = 0;else comb[i][j] = comb[i-1][j] + comb[i-1][j-1];for (int i = 0; i < m; ++i) {vector<mint> tmp(1 << 17, 0);for (int x = 300 - b[i]; x <= 300 + a[i]; ++x) {mint t = 1;for (int j = i; j < n; j += m)t *= comb[a[j] + b[j]][x - 300 + b[j]];tmp[x] = t;}NTT::ntt(tmp, false);for (int j = 0; j < 1 << 17; ++j)(i < m / 2 ? q1 : q2)[j] *= tmp[j];}NTT::ntt(q1, true);NTT::ntt(q2, true);const int offset = 300 * m;mint ans = 0;for (int i = 0; i <= offset; ++i)ans += q1[i] * q2[offset - i];cout << ans.value() << '\n';}