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