結果
問題 |
No.3174 勝ち残りじゃんけん
|
ユーザー |
|
提出日時 | 2025-02-25 02:18:07 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 44 ms / 2,000 ms |
コード長 | 1,695 bytes |
コンパイル時間 | 4,279 ms |
コンパイル使用メモリ | 252,188 KB |
実行使用メモリ | 6,820 KB |
最終ジャッジ日時 | 2025-02-25 02:19:46 |
合計ジャッジ時間 | 5,347 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 17 |
ソースコード
#include <bits/stdc++.h> #include <atcoder/all> using namespace std; using mint = atcoder::modint998244353; int main(){ ios::sync_with_stdio(false); cin.tie(0); // 入力を受け取る int n; cin >> n; // 2項係数を前計算 vector<mint> binom(n + 1); binom[0] = binom[n] = 1; mint tmp = 1; for(int i = 1; 2 * i <= n; i++){ tmp *= mint::raw(n + 1 - i); tmp *= mint::raw(i).inv(); binom[i] = binom[n - i] = tmp; } // i人でじゃんけんしたときに引き分けでない手の出し方が何通りあるかの逆数 vector<mint> ndraw_inv(n + 1); mint pow2 = 2; for(int i = 2; i <= n; i++){ pow2 += pow2; ndraw_inv[i] = (pow2 - 2).inv(); } // 残り1人になるまでに i を経由する確率 dp[i] vector<mint> dp(n + 1); dp[n] = 1; // 期待値 vector<mint> ans(n + 1); mint tot = 0, pow3 = mint(3).pow(n - 1), div = mint(3).inv(); for(int i = n; i >= 2; i--){ ans[i] = tot; mint coef = ndraw_inv[i] * dp[i]; // iを経由する確率と引き分け状態を脱出するまでの期待値の積を取る tot += pow3 * coef; pow3 *= div; // 減る人数をjとしてループを回す for(int j = 1; j <= i - 1; j++){ // i 人から j 人の敗者を選ぶ // (グー、チョキ), (チョキ、パー), (パー、グー)の3通り dp[i - j] += binom[j] * coef; binom[j] -= binom[j - 1]; } } ans[1] = tot; // 答えを出力 for(int i = 1; i <= n; i++){ cout << ans[i].val() << (i == n ? '\n' : ' '); } }