結果
| 問題 | 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 |
| 記録 | |
| コンパイル時間 | 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 |
ソースコード
#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";
}
potato167