結果

問題 No.2413 Multiple of 99
ユーザー KumaTachiRen
提出日時 2023-08-11 23:47:51
言語 C++23
(gcc 13.3.0 + boost 1.87.0)
結果
TLE  
(最新)
AC  
(最初)
実行時間 -
コード長 8,766 bytes
コンパイル時間 9,932 ms
コンパイル使用メモリ 356,496 KB
実行使用メモリ 110,788 KB
最終ジャッジ日時 2024-11-18 19:35:28
合計ジャッジ時間 128,325 ms
ジャッジサーバーID
(参考情報)
judge2 / judge5
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other AC * 14 TLE * 7
権限があれば一括ダウンロードができます

ソースコード

diff #
プレゼンテーションモードにする

#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#include <atcoder/all>
using namespace std;
using namespace atcoder;
struct Fast {
Fast() {
std::cin.tie(nullptr);
ios::sync_with_stdio(false);
cout << setprecision(10);
}
} fast;
#define popcount(x) __builtin_popcount(x)
#define all(a) (a).begin(), (a).end()
#define contains(a, x) ((a).find(x) != (a).end())
#define rep(i, a, b) for (int i = (a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (a); i--)
#define writejoin(s, a) rep(_i, 0, (a).size()) cout << (a)[_i] << (_i + 1 < (int)(a).size() ? s : "\n");
#define YN(b) cout << ((b) ? "YES" : "NO") << "\n";
#define Yn(b) cout << ((b) ? "Yes" : "No") << "\n";
#define yn(b) cout << ((b) ? "yes" : "no") << "\n";
using ll = long long;
using mint = modint998244353;
template <typename mint>
class Factorial {
public:
Factorial(int max) : n(max) {
f = vector<mint>(n + 1);
finv = vector<mint>(n + 1);
f[0] = 1;
for (int i = 1; i <= n; i++) f[i] = f[i - 1] * i;
finv[n] = f[n].inv();
for (int i = n; i > 0; i--) finv[i - 1] = finv[i] * i;
}
mint fact(int k) {
assert(0 <= k && k <= n);
return f[k];
}
mint fact_inv(int k) {
assert(0 <= k && k <= n);
return finv[k];
}
mint binom(int k, int r) {
assert(0 <= k && k <= n);
if (r < 0 || r > k) return 0;
return f[k] * finv[r] * finv[k - r];
}
mint inv(int k) {
assert(0 < k && k <= n);
return finv[k] * f[k - 1];
}
private:
int n;
vector<mint> f, finv;
};
template <typename mint>
struct FormalPowerSeries : vector<mint> {
using vector<mint>::vector;
using FPS = FormalPowerSeries;
FPS &operator+=(const FPS &r) {
if (r.size() > this->size()) this->resize(r.size());
for (int i = 0; i < (int)r.size(); i++) (*this)[i] += r[i];
return *this;
}
FPS &operator+=(const mint &r) {
if (this->empty()) this->resize(1);
(*this)[0] += r;
return *this;
}
FPS &operator-=(const FPS &r) {
if (r.size() > this->size()) this->resize(r.size());
for (int i = 0; i < (int)r.size(); i++) (*this)[i] -= r[i];
return *this;
}
FPS &operator-=(const mint &r) {
if (this->empty()) this->resize(1);
(*this)[0] -= r;
return *this;
}
FPS &operator*=(const mint &v) {
for (int k = 0; k < (int)this->size(); k++) (*this)[k] *= v;
return *this;
}
FPS &operator*=(const FPS &r) {
auto c = convolution<mint>((*this), r);
this->resize(c.size());
for (int i = 0; i < (int)c.size(); i++) (*this)[i] = c[i];
return *this;
}
FPS &operator/=(const FPS &r) {
if (this->size() < r.size()) {
this->clear();
return *this;
}
int n = this->size() - r.size() + 1;
if ((int)r.size() <= 64) {
FPS f(*this), g(r);
g.shrink();
mint coeff = g.at(g.size() - 1).inv();
for (auto &x : g) x *= coeff;
int deg = (int)f.size() - (int)g.size() + 1;
int gs = g.size();
FPS quo(deg);
for (int i = deg - 1; i >= 0; i--) {
quo[i] = f[i + gs - 1];
for (int j = 0; j < gs; j++) f[i + j] -= quo[i] * g[j];
}
*this = quo * coeff;
this->resize(n, mint(0));
return *this;
}
return *this = ((*this).rev().pre(n) * r.rev().inv(n)).pre(n).rev();
}
FPS &operator%=(const FPS &r) {
*this -= *this / r * r;
shrink();
return *this;
}
FPS operator+(const FPS &r) const { return FPS(*this) += r; }
FPS operator+(const mint &v) const { return FPS(*this) += v; }
FPS operator-(const FPS &r) const { return FPS(*this) -= r; }
FPS operator-(const mint &v) const { return FPS(*this) -= v; }
FPS operator*(const FPS &r) const { return FPS(*this) *= r; }
FPS operator*(const mint &v) const { return FPS(*this) *= v; }
FPS operator/(const FPS &r) const { return FPS(*this) /= r; }
FPS operator%(const FPS &r) const { return FPS(*this) %= r; }
FPS operator-() const {
FPS ret(this->size());
for (int i = 0; i < (int)this->size(); i++) ret[i] = -(*this)[i];
return ret;
}
void shrink() {
while (this->size() && this->back() == mint(0)) this->pop_back();
}
FPS rev() const {
FPS ret(*this);
reverse(begin(ret), end(ret));
return ret;
}
FPS dot(FPS r) const {
FPS ret(min(this->size(), r.size()));
for (int i = 0; i < (int)ret.size(); i++) ret[i] = (*this)[i] * r[i];
return ret;
}
FPS pre(int sz) const {
return FPS(begin(*this), begin(*this) + min((int)this->size(), sz));
}
FPS operator>>(int sz) const {
if ((int)this->size() <= sz) return {};
FPS ret(*this);
ret.erase(ret.begin(), ret.begin() + sz);
return ret;
}
FPS operator<<(int sz) const {
FPS ret(*this);
ret.insert(ret.begin(), sz, mint(0));
return ret;
}
FPS diff() const {
const int n = (int)this->size();
FPS ret(max(0, n - 1));
mint one(1), coeff(1);
for (int i = 1; i < n; i++) {
ret[i - 1] = (*this)[i] * coeff;
coeff += one;
}
return ret;
}
FPS integral() const {
const int n = (int)this->size();
FPS ret(n + 1);
ret[0] = mint(0);
if (n > 0) ret[1] = mint(1);
auto mod = mint::get_mod();
for (int i = 2; i <= n; i++) ret[i] = (-ret[mod % i]) * (mod / i);
for (int i = 0; i < n; i++) ret[i + 1] *= (*this)[i];
return ret;
}
mint eval(mint x) const {
mint r = 0, w = 1;
for (auto &v : *this) r += w * v, w *= x;
return r;
}
FPS log(int deg = -1) const {
assert((*this)[0] == mint(1));
if (deg == -1) deg = (int)this->size();
return (this->diff() * this->inv(deg)).pre(deg - 1).integral();
}
FPS pow(int64_t k, int deg = -1) const {
const int n = (int)this->size();
if (deg == -1) deg = n;
if (k == 0) {
FPS ret(deg);
if (deg) ret[0] = 1;
return ret;
}
for (int i = 0; i < n; i++) {
if ((*this)[i] != mint(0)) {
mint rev = mint(1) / (*this)[i];
FPS ret = (((*this * rev) >> i).log(deg) * k).exp(deg);
ret *= (*this)[i].pow(k);
ret = (ret << (i * k)).pre(deg);
if ((int)ret.size() < deg) ret.resize(deg, mint(0));
return ret;
}
if (__int128_t(i + 1) * k >= deg) return FPS(deg, mint(0));
}
return FPS(deg, mint(0));
}
FPS inv(int deg = -1) const {
assert((*this)[0] != mint(0));
if (deg == -1) deg = (*this).size();
FPS ret{mint(1) / (*this)[0]};
for (int i = 1; i < deg; i <<= 1)
ret = (ret + ret - ret * ret * (*this).pre(i << 1)).pre(i << 1);
return ret.pre(deg);
}
FPS exp(int deg = -1) const {
assert((*this)[0] == mint(0));
if (deg == -1) deg = (*this).size();
FPS ret{mint(1)};
for (int i = 1; i < deg; i <<= 1)
ret = (ret * ((*this).pre(i << 1) - ret.log(i << 1) + 1)).pre(i << 1);
return ret.pre(deg);
}
};
vector<mint> mul(const vector<mint> &f, const vector<mint> &g) {
auto h = convolution(f, g);
rrep(i, 99, h.size()) h[i - 99] += h[i];
if ((int)h.size() > 99) h.resize(99);
return h;
}
using fps = FormalPowerSeries<mint>;
int main() {
int n, k;
cin >> n >> k;
Factorial<mint> fact(2000000);
int mf = n / 2;
fps f;
{
fps fp = fps(mf * 10 + 1, 0);
fps fq = fps(mf + 1, 0);
rep(i, 0, mf + 1) {
fq[i] = fact.binom(mf, i);
if (i % 2 == 1) {
fq[i] = -fq[i];
}
fp[i * 10] = fq[i];
}
f = fp * fq.inv(mf * 9 + 1);
f.resize(mf * 9 + 1);
}
fps g(f.size());
rep(i, 0, f.size()) g[i] = f[i];
if (n & 1) g *= fps(10, 1);
f.resize(g.size());
vector<fps> fr(99), gr(99);
queue<fps> qf, qg, qh;
rep(r, 0, 99) {
if (r >= (int)g.size()) {
fr[r] = fps{};
gr[r] = fps{};
} else {
for (int v = r; v < (int)g.size(); v += 99) {
qf.push(fps{f[v]});
qg.push(fps{g[v]});
qh.push(fps{1, -v});
}
while (qf.size() > 1) {
auto f1 = qf.front();
qf.pop();
auto f2 = qf.front();
qf.pop();
auto g1 = qg.front();
qg.pop();
auto g2 = qg.front();
qg.pop();
auto h1 = qh.front();
qh.pop();
auto h2 = qh.front();
qh.pop();
qf.push(f1 * h2 + f2 * h1);
qg.push(g1 * h2 + g2 * h1);
qh.push(h1 * h2);
}
auto h = qh.front().inv(k + 1);
fr[r] = qf.front() * h;
gr[r] = qg.front() * h;
qf.pop();
qg.pop();
qh.pop();
}
}
mint ans = 0;
rep(v, 0, 99) {
int w = (99 - v) * 10 % 99;
auto frr = fr[v];
auto grr = gr[w];
rep(i, 0, fr[v].size()) {
int j = k - i;
if (j < (int)gr[w].size()) ans += fact.binom(k, i) * frr[i] * grr[j];
}
}
cout << ans.val() << "\n";
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
0