結果

問題 No.3451 Same Numbers
コンテスト
ユーザー 👑 potato167
提出日時 2026-02-19 17:51:23
言語 C++17
(gcc 15.2.0 + boost 1.89.0)
結果
AC  
実行時間 571 ms / 2,000 ms
コード長 3,244 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 2,638 ms
コンパイル使用メモリ 233,620 KB
実行使用メモリ 7,976 KB
最終ジャッジ日時 2026-02-20 20:57:03
合計ジャッジ時間 8,428 ms
ジャッジサーバーID
(参考情報)
judge3 / judge4
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other AC * 37
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

#include <bits/stdc++.h>
using namespace std;
#include <atcoder/modint>
using mint = atcoder::modint998244353;
#define rep(i, a, b) for (int i = a; i < b; i++)

namespace po167{
template<class T>
struct Binomial{
    std::vector<T> fact_vec, fact_inv_vec;
    void extend(int m = -1){
        int n = fact_vec.size();
        if (m == -1) m = n * 2;
        if (n >= m) return;
        fact_vec.resize(m);
        fact_inv_vec.resize(m);
        for (int i = n; i < m; i++){
            fact_vec[i] = fact_vec[i - 1] * T(i);
        }
        fact_inv_vec[m - 1] = T(1) / fact_vec[m - 1];
        for (int i = m - 1; i > n; i--){
            fact_inv_vec[i - 1] = fact_inv_vec[i] * T(i);
        }
    }
    Binomial(int MAX = 0){
        fact_vec.resize(1, T(1));
        fact_inv_vec.resize(1, T(1));
        extend(MAX + 1);
    }

    T fact(int i){
        if (i < 0) return 0;
        while (int(fact_vec.size()) <= i) extend();
        return fact_vec[i];
    }
    T invfact(int i){
        if (i < 0) return 0;
        while (int(fact_inv_vec.size()) <= i) extend();
        return fact_inv_vec[i];
    }
    T C(int a, int b){
        if (a < b || b < 0) return 0;
        return fact(a) * invfact(b) * invfact(a - b);
    }
    T inv(int a){
        if (a < 0) return inv(-a) * T(-1);
        if (a == 0) return 1;
        return fact(a - 1) * invfact(a);
    }
};
}

// O(V^1.5)
vector<mint> solve4(int N, int M, int E, bool cl = false){
    po167::Binomial<mint> table;
    vector<mint> res(N, 1);
    int B = 0;
    while (B * B * 3 < M && B < N - 1) B++;
    
    vector<mint> sc(M + 1);
    rep(i, 0, M + 1) sc[i] = (mint(i)).pow(E);
    res[N - 1] = sc[(M - 1) / N + 1];

    rep(k, 0, B){
        mint inv = table.inv(N - k - 1);
        // x 回中 y 回未満を常に管理する
        int x = M;
        int y = 0;
        mint tmp = 0;
        mint tmp2 = table.inv(N - k).pow(x) * (mint(N - k - 1)).pow(x);
        int a = 1;
        mint adX = inv * (N - k);
        while (true){
            int A = M - 1 - k * a;
            int B = a;
            if (A < B) break;
            while (A < x){
                // (x - 1, y - 1) -> (x, y)
                tmp += table.C(x - 1, y - 1) * tmp2;
                x--;
                tmp2 *= adX;
            }
            while (y < B){
                tmp += table.C(A, y) * tmp2;
                tmp2 *= inv;
                y++;
            }
            res[k] += (1 - tmp) * (sc[a + 1] - sc[a]);
            a++;
        }
    }
    rep(k, B, N - 1){
        mint inv = table.inv(N - k - 1);
        // N - 1 - k * a 回中 a 回未満
        int a = 1;
        while (true){
            int A = M - 1 - k * a;
            int B = a;
            if (A < B) break;
            mint sum = 1;
            mint tmp = table.inv(N - k).pow(A) * (mint(N - k - 1)).pow(A);
            rep(j, 0, a){
                sum -= table.C(A, j) * tmp;
                tmp *= inv;
            }
            res[k] += sum * (sc[a + 1] - sc[a]);
            a++;
        }
    }
    return res;
}
int main(){
	std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

	int N, M, E;
	cin >> N >> M >> E;
	
	auto ans = solve4(N, M, E);
	for (auto x : ans) cout << x.val() << "\n";
}
0