結果
| 問題 |
No.2807 Have Another Go (Easy)
|
| コンテスト | |
| ユーザー |
qwewe
|
| 提出日時 | 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;
}
qwewe