P8768 [蓝桥杯 2021 国 A] 积木 题解
首先有一个观察是
容易发现
随后考虑前两个部分如何计算。
首先可以发现,从第二行开始,每一行的积木数量都落在一个区间
我们发现目前的生成函数的最低项是非常数项,因此不妨将系数进行偏移。令
第
然后可以枚举
依照上方描述,有
前两部分的答案就是
你可能要问了:上界呢?
求和的上界是偏移后的上界,也就是
发现
你问这个方法怎么做?我们发现对
多项式的次数无法降低,我们就需要寻找一种方法
不妨考虑较广泛的情况,即递推
的前
通过与P5434类似的手法,我们可以得到
即
这自然导出了递推方案。因此可以做到
统计答案并非瓶颈,因此做到了
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for (register int i = (a), i##_ = (b) + 1; i < i##_; ++i)
#define pre(i,a,b) for (register int i = (a), i##_ = (b) - 1; i > i##_; --i)
const int N = 2e7 + 10, mod = 998244353, g = 3;
int n, www, l, r, x, y, z, A[N], B[N], ans, len, lim;
int inv[N];
int qp(int a, int b) {
int ret = 1;
while (b) {
if (b & 1) ret = 1ll * ret * a % mod;
a = 1ll * a * a % mod;
b >>= 1;
} return ret;
}
void get(int f[], int n, int m) {
f[0] = 1;
rep(i,1,len) {
f[i] = f[i - 1];
if (i - n + 1 >= 0) f[i] = (f[i] - 1ll * n * f[i - n] % mod + mod) % mod;
if (i - n >= 0) f[i] = (f[i] + 1ll * (n - 1) * f[i - n - 1]) % mod;
f[i] = 1ll * f[i] * m % mod;
if (i - 1 >= 0) f[i] = (f[i] + 1ll * (i - 1) * f[i - 1]) % mod;
if (i - n >= 0) f[i] = (f[i] + 1ll * (i - n) * f[i - n]) % mod;
if (i - n - 1 >= 0) f[i] = (f[i] - 1ll * (i - n - 1) * f[i - n - 1] % mod + mod) % mod;
f[i] = 1ll * f[i] * inv[i] % mod;
}
}
signed main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> www >> l >> r >> x >> y >> z;
len = n * (r - l) + 1;
inv[0] = inv[1] = 1;
rep(i,2,len) inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod;
get(A, r - l + 1, x - 1);
get(B, r - l + 1, y - x);
for (int i = 0, p; i < len; ++ i) {
p = z * (www + (x - 1) * l + i) - (www + (y - 1) * l + i);
if (p < 0) continue; if (p >= len) break;
ans = (ans + 1ll * A[i] * B[p]) % mod;
} cout << 1ll * ans * qp(r - l + 1, n - y) % mod;
}