篮球比赛题解
szh_AK_all · · 题解
出题人题解。
正解
定义
int sum = 0;
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= k; j++)
f[i] = (f[i] + aa[j] * qpow(i, j) % mod) % mod;
sum = (sum + f[i]) % mod;
}
for (int i = 1; i <= n; i++)
dp[i] = f[i] * qpow(sum, mod - 2) % mod;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
dp[i + j] = (dp[i + j] + dp[i] * p[j] % mod) % mod;
sum = 0;
for (int i = 1; i <= n; i++)
sum = (sum + dp[i]) % mod;
cout << sum;
其中
最终期望胜利场数即为
由于这种转移时间复杂度很慢,所以考虑矩阵乘法。
首先,求出
接着根据二项式展开构造
两个矩阵相乘,可得出:
满足矩阵乘法。由于要用到分数取模形式,所以设
接着求出
接着构造
两个矩阵相乘得到:
Code
by 2023gdgz01
#include <cstdio>
#include <cstring>
long long n, m, k, inv, maxmk, p[55], A[55], c[55][55];
struct matrix {
long long c[105][105];
inline matrix operator* (const matrix &r) {
matrix temp;
memset(temp.c, 0, sizeof(temp.c));
for (register int i = 1; i <= maxmk; ++i)
for (register int j = 1; j <= maxmk; ++j)
for (register int y = 1; y <= maxmk; ++y)
temp.c[i][j] = (temp.c[i][j] + c[i][y] * r.c[y][j] % 998244353) % 998244353;
return temp;
}
};
matrix a, ans;
inline int max(int x, int y) {
if (x > y)
return x;
return y;
}
inline void matrix_quick_power(matrix a, long long b) {
while (b) {
if (b & 1)
ans = ans * a;
a = a * a;
b >>= 1;
}
}
inline long long quick_power(long long a, long long b) {
long long ans = 1;
while (b) {
if (b & 1)
ans = ans * a % 998244353;
a = a * a % 998244353;
b >>= 1;
}
return ans % 998244353;
}
int main() {
scanf("%lld%lld%lld", &n, &m, &k);
for (register int i = 1; i <= m; ++i)
scanf("%lld", p + i);
for (register int i = 0; i <= k; ++i)
scanf("%lld", A + i);
maxmk = max(m, k) + 1 << 1;
for (register int i = 0; i <= k; ++i) {
c[i][0] = 1;
for (register int j = 1; j <= i; ++j)
c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % 998244353;
}
for (register int i = 2; i <= k + 2; ++i)
ans.c[1][i] = 1;
a.c[1][1] = 1;
for (register int i = 2; i <= k + 2; ++i) {
a.c[i][1] = A[i - 2];
for (register int j = i; j <= k + 2; ++j)
a.c[i][j] = c[j - 2][i - 2];
}
matrix_quick_power(a, n);
inv = quick_power(ans.c[1][1], 998244351);
memset(ans.c, 0, sizeof(ans.c));
memset(a.c, 0, sizeof(a.c));
for (register int i = m + 2; i <= m + k + 2; ++i)
ans.c[1][i] = 1;
a.c[1][1] = a.c[2][1] = 1;
for (register int i = 2; i <= m + 1; ++i) {
a.c[i][2] = p[i - 1];
if (i != m + 1)
a.c[i][i + 1] = 1;
}
for (register int i = m + 2; i <= m + k + 2; ++i) {
a.c[i][2] = inv * A[i - m - 2] % 998244353;
for (register int j = i; j <= m + k + 2; ++j)
a.c[i][j] = c[j - m - 2][i - m - 2];
}
matrix_quick_power(a, n + 1);
printf("%lld", ans.c[1][1]);
return 0;
}