結果
問題 |
No.2807 Have Another Go (Easy)
|
ユーザー |
![]() |
提出日時 | 2025-05-14 13:21:11 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 2,328 ms / 3,000 ms |
コード長 | 4,906 bytes |
コンパイル時間 | 1,041 ms |
コンパイル使用メモリ | 86,088 KB |
実行使用メモリ | 11,200 KB |
最終ジャッジ日時 | 2025-05-14 13:23:49 |
合計ジャッジ時間 | 61,507 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 46 |
ソースコード
#include <iostream> #include <vector> #include <numeric> #include <algorithm> using namespace std; long long MOD = 998244353; const int D = 6; // Dimension of recurrence // Matrix multiplication for DxD matrices vector<vector<long long>> multiply(const vector<vector<long long>>& A, const vector<vector<long long>>& B) { vector<vector<long long>> C(D + 1, vector<long long>(D + 1, 0)); for (int i = 0; i <= D; ++i) { for (int j = 0; j <= D; ++j) { for (int k = 0; k <= D; ++k) { C[i][j] = (C[i][j] + A[i][k] * B[k][j]) % MOD; } } } return C; } // Matrix power using binary exponentiation vector<vector<long long>> matrix_pow(vector<vector<long long>> A, long long p) { vector<vector<long long>> res(D + 1, vector<long long>(D + 1, 0)); for (int i = 0; i <= D; ++i) res[i][i] = 1; A[D][D] = 1; // Ensure the (D,D) element for affine transform is 1 initially while (p > 0) { if (p & 1) res = multiply(res, A); A = multiply(A, A); p >>= 1; } return res; } // Apply matrix to vector V = M * U vector<long long> apply_matrix_to_vector(const vector<vector<long long>>& M, const vector<long long>& U) { vector<long long> V(D + 1, 0); for (int i = 0; i <= D; ++i) { for (int j = 0; j <= D; ++j) { V[i] = (V[i] + M[i][j] * U[j]) % MOD; } } return V; } int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); int N_val, M_val, k_queries; cin >> N_val >> M_val >> k_queries; // M_val is always 2 int limit_sum = 2 * N_val; vector<long long> f(limit_sum + D, 0); f[0] = 1; for (int i = 1; i < limit_sum + D; ++i) { for (int d = 1; d <= D; ++d) { if (i - d >= 0) { f[i] = (f[i] + f[i - d]) % MOD; } } } vector<vector<long long>> T_std(D + 1, vector<long long>(D + 1, 0)); for (int j = 0; j < D; ++j) { T_std[0][j] = 1; } for (int i = 1; i < D; ++i) { T_std[i][i - 1] = 1; } T_std[D][D] = 1; vector<vector<long long>> T_reset_proto(D + 1, vector<long long>(D + 1, 0)); // First row of M_zr is all zeros, so T_reset_proto[0][j] for j<D are 0. for (int i = 1; i < D; ++i) { T_reset_proto[i][i - 1] = 1; } T_reset_proto[D][D] = 1; vector<int> C_values(k_queries); for (int i = 0; i < k_queries; ++i) { cin >> C_values[i]; } for (int qi = 0; qi < k_queries; ++qi) { int C = C_values[qi]; vector<long long> U(D + 1, 0); // Represents (g[x-1]...g[x-6], 1)^T U[D] = 1; // for affine transformation // Initial state corresponds to g[-1]...g[-6] all 0. long long current_x = -1; vector<long long> critical_points; critical_points.push_back(C); if (C + N_val < limit_sum) { critical_points.push_back(C + N_val); } for (long long p : critical_points) { long long segment_len = p - 1 - current_x; if (segment_len > 0) { vector<vector<long long>> T_std_pow_L = matrix_pow(T_std, segment_len); U = apply_matrix_to_vector(T_std_pow_L, U); } current_x = p - 1; // Reset at point p vector<vector<long long>> T_reset_concrete = T_reset_proto; T_reset_concrete[0][D] = f[p]; // B_x vector's first component is f[p] U = apply_matrix_to_vector(T_reset_concrete, U); current_x = p; } long long final_segment_len = (limit_sum - 1) - current_x; if (final_segment_len > 0) { vector<vector<long long>> T_std_pow_L = matrix_pow(T_std, final_segment_len); U = apply_matrix_to_vector(T_std_pow_L, U); } // Now U contains (g[2N-1], g[2N-2], ..., g[2N-6], 1)^T vector<long long> g_values(D); for(int i=0; i<D; ++i) { g_values[i] = U[i]; } long long ans_C = 0; for (int s_idx = 0; s_idx < D; ++s_idx) { long long s = limit_sum - 1 - s_idx; // s goes from 2N-1 down to 2N-6 if (s < 0) continue; long long term_rolls_count = 0; // Number of d in [1,6] such that s+d >= limit_sum // d >= limit_sum - s // Smallest d is max(1, limit_sum - s) // Largest d is 6 // If max(1, limit_sum - s) > 6, count is 0 // Else count = 6 - max(1, limit_sum - s) + 1 long long min_d_to_terminate = limit_sum - s; if (min_d_to_terminate <= D) { // D is 6 term_rolls_count = D - max(1LL, min_d_to_terminate) + 1; } ans_C = (ans_C + g_values[s_idx] * term_rolls_count) % MOD; } cout << ans_C << "\n"; } return 0; }