結果
| 問題 |
No.1241 Eternal Tours
|
| コンテスト | |
| ユーザー |
hitonanode
|
| 提出日時 | 2020-08-25 22:32:45 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 609 ms / 6,000 ms |
| コード長 | 5,624 bytes |
| コンパイル時間 | 1,220 ms |
| コンパイル使用メモリ | 84,064 KB |
| 最終ジャッジ日時 | 2025-01-13 14:47:20 |
|
ジャッジサーバーID (参考情報) |
judge3 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 4 |
| other | AC * 40 |
ソースコード
#include <cassert>
#include <iostream>
#include <vector>
#include <set>
template <int mod>
struct ModInt
{
using lint = long long;
static int get_mod() { return mod; }
static int get_primitive_root() {
assert(mod == 998244353);
return 3;
}
int val;
constexpr ModInt() : val(0) {}
constexpr ModInt &_setval(lint v) { val = (v >= mod ? v - mod : v); return *this; }
constexpr ModInt(lint v) { _setval(v % mod + mod); }
explicit operator bool() const { return val != 0; }
constexpr ModInt operator+(const ModInt &x) const { return ModInt()._setval((lint)val + x.val); }
constexpr ModInt operator-(const ModInt &x) const { return ModInt()._setval((lint)val - x.val + mod); }
constexpr ModInt operator*(const ModInt &x) const { return ModInt()._setval((lint)val * x.val % mod); }
constexpr ModInt operator/(const ModInt &x) const { return ModInt()._setval((lint)val * x.inv() % mod); }
constexpr ModInt operator-() const { return ModInt()._setval(mod - val); }
constexpr ModInt &operator+=(const ModInt &x) { return *this = *this + x; }
constexpr ModInt &operator-=(const ModInt &x) { return *this = *this - x; }
constexpr ModInt &operator*=(const ModInt &x) { return *this = *this * x; }
constexpr ModInt &operator/=(const ModInt &x) { return *this = *this / x; }
friend constexpr ModInt operator+(lint a, const ModInt &x) { return ModInt()._setval(a % mod + x.val); }
friend constexpr ModInt operator-(lint a, const ModInt &x) { return ModInt()._setval(a % mod - x.val + mod); }
friend constexpr ModInt operator*(lint a, const ModInt &x) { return ModInt()._setval(a % mod * x.val % mod); }
friend constexpr ModInt operator/(lint a, const ModInt &x) { return ModInt()._setval(a % mod * x.inv() % mod); }
constexpr bool operator==(const ModInt &x) const { return val == x.val; }
constexpr bool operator!=(const ModInt &x) const { return val != x.val; }
friend std::istream &operator>>(std::istream &is, ModInt &x) { lint t; is >> t; x = ModInt(t); return is; }
friend std::ostream &operator<<(std::ostream &os, const ModInt &x) { os << x.val; return os; }
constexpr lint power(lint n) const {
lint ans = 1, tmp = this->val;
while (n) {
if (n & 1) ans = ans * tmp % mod;
tmp = tmp * tmp % mod;
n /= 2;
}
return ans;
}
constexpr lint inv() const { return this->power(mod - 2); }
};
template <typename MODINT>
void ntt(std::vector<MODINT> &a, bool is_inverse = false)
{
int n = a.size();
if (n == 1) return;
static const int mod = MODINT::get_mod();
static const MODINT root = MODINT::get_primitive_root();
assert(__builtin_popcount(n) == 1 and (mod - 1) % n == 0);
static std::vector<MODINT> w{1}, iw{1};
for (int m = w.size(); m < n / 2; m *= 2)
{
MODINT dw = root.power((mod - 1) / (4 * m)), dwinv = 1 / dw;
w.resize(m * 2), iw.resize(m * 2);
for (int i = 0; i < m; i++) w[m + i] = w[i] * dw, iw[m + i] = iw[i] * dwinv;
}
if (!is_inverse) {
for (int m = n; m >>= 1;) {
for (int s = 0, k = 0; s < n; s += 2 * m, k++) {
for (int i = s; i < s + m; i++) {
MODINT x = a[i], y = a[i + m] * w[k];
a[i] = x + y, a[i + m] = x - y;
}
}
}
}
else {
for (int m = 1; m < n; m *= 2) {
for (int s = 0, k = 0; s < n; s += 2 * m, k++) {
for (int i = s; i < s + m; i++) {
MODINT x = a[i], y = a[i + m];
a[i] = x + y, a[i + m] = (x - y) * iw[k];
}
}
}
int n_inv = MODINT(n).inv();
for (auto &v : a) v *= n_inv;
}
}
template <typename MODINT>
void ntt2d(std::vector<std::vector<MODINT>> &mat)
{
for (auto &vec : mat) ntt(vec, false);
int h = mat.size(), w = mat[0].size();
for (int j = 0; j < w; j++)
{
std::vector<MODINT> v(h);
for (int i = 0; i < h; i++) v[i] = mat[i][j];
ntt(v, false);
for (int i = 0; i < h; i++) mat[i][j] = v[i];
}
}
template <typename MODINT>
void ntt2dinv(std::vector<std::vector<MODINT>> &mat)
{
int h = mat.size(), w = mat[0].size();
for (int j = 0; j < w; j++)
{
std::vector<MODINT> v(h);
for (int i = 0; i < h; i++) v[i] = mat[i][j];
ntt(v, true);
for (int i = 0; i < h; i++) mat[i][j] = v[i];
}
for (auto &vec : mat) ntt(vec, true);
}
using namespace std;
using mint = ModInt<998244353>;
int main()
{
int X, Y;
long long T;
int a, b, c, d;
cin >> X >> Y >> T >> a >> b >> c >> d;
assert(X >= 1 and Y >= 1);
assert(X + Y <= 18);
assert(T >= 1 and T <= 1'000'000'000'000'000'000LL);
assert(a >= 1 and a < (1 << X));
assert(b >= 1 and b < (1 << Y));
assert(c >= 1 and c < (1 << X));
assert(d >= 1 and d < (1 << Y));
vector dp(1 << (X + 1), vector<mint>(1 << (Y + 1)));
dp[a - 1][b - 1] = 1;
dp[a - 1][dp[a - 1].size() - b - 1] = -1;
dp[dp.size() - a - 1][b - 1] = -1;
dp[dp.size() - a - 1][dp[a - 1].size() - b - 1] = 1;
vector trans(1 << (X + 1), vector<mint>(1 << (Y + 1)));
trans[0][0] = trans[0][1] = trans[0].back() = trans[1][0] = trans.back()[0] = 1;
ntt2d(dp);
ntt2d(trans);
for (size_t i = 0; i < dp.size(); i++)
{
for (size_t j = 0; j < dp[i].size(); j++)
{
dp[i][j] *= trans[i][j].power(T);
}
}
ntt2dinv(dp);
cout << dp[c - 1][d - 1] << '\n';
}
hitonanode