官方题解|巨大的表格
2025-02-05 20:28:54
发布于:北京
66阅读
0回复
0点赞
题目解析
我们可以先计算出 列的所有元素的值,然后考虑表格中每一列元素的值,可以发现,对于 列的 个元素的值,可以完全由 列的元素得到:
由于 号元素每次加 ,所以我们可以考虑在最后给表格加一行全为 的元素作为 行上的元素,接着可以把转移写成矩阵的形式。
那么我们有:
由于 很大,对于每个查询 ,我们可以使用矩阵快速幂来计算出表格中 上的所有元素。
整个算法时间复杂度:。
AC代码
#include <bits/stdc++.h>
namespace Matrix {
template<class T>
using Mat = std::vector<std::vector<T>>;
template<class T>
Mat<T> e(int n) {
Mat<T> a(n, std::vector<T>(n, T()));
for (int i = 0; i < n; ++i)
a[i][i] = 1;
return a;
}
template<class T>
Mat<T> multi(const Mat<T> &a, const Mat<T> &b) {
assert(!a.empty() and !b.empty() and a[0].size() == b.size());
int n = a.size(), m = b.size(), p = b[0].size();
Mat<T> c(n, std::vector<T>(m, T()));
for (int i = 0; i < n; ++i)
for (int k = 0; k < m; ++k)
for (int j = 0; j < p; ++j)
c[i][j] += a[i][k] * b[k][j];
return c;
}
template<class T>
Mat<T> pow(Mat<T> x, unsigned long long n) {
assert(!x.empty() and x.size() == x[0].size());
auto res = e<T>(x.size());
while (n) {
if (n & 1)
res = multi(res, x);
x = multi(x, x);
n >>= 1;
}
return res;
}
template<class T>
void print(Mat<T> mat) {
if (mat.empty()) return;
int n = mat.size(), m = mat[0].size();
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
std::cout << mat[i][j] << " \n"[j + 1 == m];
}
}
template<int m>
class Modint {
private:
unsigned int _v;
static constexpr unsigned int umod() {return m;}
public:
static constexpr int mod() {return m;}
static Modint raw(int v) {
Modint x;
x._v = v;
return x;
}
Modint() : _v(0) {}
template<class T>
Modint(T v) {
long long x = (long long)(v % (long long)(umod()));
if (x < 0) x += umod();
_v = (unsigned int)(x);
}
unsigned int val() const {return _v;}
Modint& operator++() {
_v++;
if (_v == umod()) _v = 0;
return *this;
}
Modint& operator--() {
if (_v == 0) _v = umod();
_v--;
return *this;
}
Modint operator++(int) {
Modint result = *this;
++*this;
return result;
}
Modint operator--(int) {
Modint result = *this;
--*this;
return result;
}
Modint& operator+=(const Modint& rhs) {
_v += rhs._v;
if (_v >= umod()) _v -= umod();
return *this;
}
Modint& operator-=(const Modint& rhs) {
_v -= rhs._v;
if (_v >= umod()) _v += umod();
return *this;
}
Modint& operator*=(const Modint& rhs) {
unsigned long long z = _v;
z *= rhs._v;
_v = (unsigned int)(z % umod());
return *this;
}
Modint& operator/=(const Modint& rhs) {return *this = *this * rhs.inv();}
Modint operator+() const {return *this;}
Modint operator-() const {return Modint() - *this;}
Modint pow(long long n) const {
if (n < 0) return pow(-n).inv();
Modint x = *this, r = 1;
while (n) {
if (n & 1) r *= x;
x *= x;
n >>= 1;
}
return r;
}
Modint inv() const {
assert(_v);
return pow(umod() - 2);
}
friend Modint operator+(const Modint& lhs, const Modint& rhs) {
return Modint(lhs) += rhs;
}
friend Modint operator-(const Modint& lhs, const Modint& rhs) {
return Modint(lhs) -= rhs;
}
friend Modint operator*(const Modint& lhs, const Modint& rhs) {
return Modint(lhs) *= rhs;
}
friend Modint operator/(const Modint& lhs, const Modint& rhs) {
return Modint(lhs) /= rhs;
}
friend bool operator==(const Modint& lhs, const Modint& rhs) {
return lhs._v == rhs._v;
}
friend bool operator!=(const Modint& lhs, const Modint& rhs) {
return lhs._v != rhs._v;
}
};
using mint = Modint<998244353>;
int main() {
std::cin.tie(nullptr)->sync_with_stdio(false);
int n, m, s, t;
std::cin >> n >> m >> s >> t;
Matrix::Mat<mint> dp = {std::vector<mint>(n + 1)};
dp[0][0] = 1;
for (int i = 1; i < n; ++i) {
int x; std::cin >> x;
dp[0][i] = dp[0][i - 1] * s + 1LL * x * t;
}
dp[0][n] = 1;
Matrix::Mat<mint> a = Matrix::e<mint>(n + 1);
a[n][0] = 1;
for (int i = 1; i < n; ++i) {
a[i][i] = t;
for (int j = i - 1; j >= 0; --j)
a[j][i] = a[j + 1][i] * s;
a[0][i] /= t;
a[n][i] = a[n][i - 1] * s;
}
int q; std::cin >> q;
while (q--) {
int r, c;
std::cin >> r >> c;
auto res = Matrix::multi(dp, Matrix::pow(a, c - 1));
std::cout << res[0][r].val() << '\n';
}
return 0;
}
这里空空如也
有帮助,赞一个