結果
問題 |
No.2807 Have Another Go (Easy)
|
ユーザー |
![]() |
提出日時 | 2025-05-14 13:01:24 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
TLE
|
実行時間 | - |
コード長 | 5,790 bytes |
コンパイル時間 | 963 ms |
コンパイル使用メモリ | 79,472 KB |
実行使用メモリ | 33,580 KB |
最終ジャッジ日時 | 2025-05-14 13:03:39 |
合計ジャッジ時間 | 5,498 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 1 TLE * 1 -- * 44 |
ソースコード
#include <iostream> #include <vector> #include <numeric> #include <algorithm> // For std::max using namespace std; // Use long long for N potentially large long long N; int M; // M is given as 2 in this version of the problem int k; vector<long long> C; // Stores the C_i values for the k queries const long long MOD = 998244353; // The modulus for calculations int main() { // Faster I/O operations ios_base::sync_with_stdio(false); cin.tie(NULL); // Read input N, M, k cin >> N >> M >> k; // Read the k values of C_i C.resize(k); for (int i = 0; i < k; ++i) { cin >> C[i]; } // Calculate the termination threshold NM. Since M=2, NM = 2N. long long NM = N * M; // Problem constraints state N >= 6, so NM >= 12. This avoids edge cases with small NM. // --- Step 1: Calculate the DP table for total ways --- // dp[x] stores the number of ways to reach state X=x without terminating before. vector<long long> dp(NM); dp[0] = 1; // Base case: There is 1 way to be at state 0 initially. // Fill the DP table up to state NM-1 for (long long x = 1; x < NM; ++x) { dp[x] = 0; // Initialize ways to reach state x // Sum contributions from previous states reachable by rolling 1 to 6 for (int d = 1; d <= 6; ++d) { if (x - d >= 0) { // Check if the previous state x-d is valid (non-negative) dp[x] = (dp[x] + dp[x - d]) % MOD; // Add ways from dp[x-d] modulo MOD } } } // --- Step 2: Calculate the total number of terminating sequences --- long long T_total = 0; // cnt[x] will store the number of dice rolls 'd' (1 to 6) that cause termination from state x (i.e., x+d >= NM) vector<long long> cnt(NM); // Calculate cnt[x] and T_total contribution for relevant states x. // Relevant states are those from which termination is possible in one step: NM-6 to NM-1. // Iterate from NM-1 down to max(0LL, NM-6) to cover these states. max(0LL, ...) handles NM < 6 case (although not needed here N>=6). for (long long x = NM - 1; x >= max(0LL, NM - 6); --x) { long long current_cnt = 0; // Count terminating rolls from state x for(int d = 1; d <= 6; ++d) { if (x + d >= NM) { // Check if rolling 'd' leads to termination current_cnt++; } } cnt[x] = current_cnt; // Store the count for state x // Add the contribution of paths ending through state x to T_total // dp[x] ways to reach state x, cnt[x] ways to terminate from x T_total = (T_total + dp[x] * cnt[x]) % MOD; } // Problem constraints: 1 <= C_i < N. This implies C_i % N != 0. // The initial state X_0=0 is always added to Y. Since 0 % N = 0, and C_i % N != 0, // the condition X_0 % N != C_i always holds. // --- Step 3: For each query C_i, calculate the answer --- vector<long long> results; // Store results for each query results.reserve(k); // Reserve space for efficiency // dp_noC[x] will store the number of ways to reach state x such that no state Y[j] satisfies Y[j] % N == C_i // This DP table is reused for each query C_i. vector<long long> dp_noC(NM); for (int i = 0; i < k; ++i) { long long current_C = C[i]; // The C value for the current query // --- Calculate dp_noC table for the current C_i --- // Base case: dp_noC[0] = 1. As discussed, X_0=0 never violates the condition. dp_noC[0] = 1; for (long long x = 1; x < NM; ++x) { dp_noC[x] = 0; // Initialize ways to reach state x under the condition for (int d = 1; d <= 6; ++d) { if (x - d >= 0) { // Check if previous state is valid long long prev_state = x - d; // The state before rolling 'd' // The condition is on states in Y = [X_0, ..., X_{T-1}]. // When calculating ways to reach state X_t=x, the state X_{t-1}=prev_state is the last state added to Y. // We must check if prev_state % N == current_C. If it is, this path is invalid for dp_noC. if (prev_state % N != current_C) { // If the condition is NOT violated by prev_state, add the ways from dp_noC[prev_state]. dp_noC[x] = (dp_noC[x] + dp_noC[prev_state]) % MOD; } } } } // --- Calculate T_C^c: total ways for the complement event --- // T_C^c = Number of terminating sequences where for all Y[j], Y[j] % N != C_i. long long T_Cc = 0; // Sum over states x from which the game can terminate (NM-6 to NM-1) for (long long x = NM - 1; x >= max(0LL, NM - 6); --x) { // The last state added to Y is x (which is X_{T-1}). // This state x must also satisfy the condition x % N != C_i for the sequence to be counted in T_C^c. if (x % N != current_C) { // If condition holds for x, add its contribution: dp_noC[x] ways to reach x satisfying condition * cnt[x] ways to terminate. T_Cc = (T_Cc + dp_noC[x] * cnt[x]) % MOD; // Use precomputed cnt[x] } } // --- Final answer for C_i --- // The required answer is Total sequences - Complement sequences. // (T_total - T_Cc + MOD) % MOD handles potential negative result from subtraction. long long ans = (T_total - T_Cc + MOD) % MOD; results.push_back(ans); // Store the answer for this query } // --- Step 4: Output results --- for (long long res : results) { cout << res << "\n"; } return 0; }