P7493 旅人1969

· · 题解

最开始以为是反演,但很快发现并不是。

考虑进行 dp 。

不难想出,有以下转移: $$f_{k, n} = \sum\limits_{x = 1}^m f_{k - 1, n - x}$$ 于是写出它的生成函数 $$g = \sum\limits_{i = 1}^m x^i$$ $$f_k = g^k$$ 那么我们要求的就是 $$h_k = \sum\limits_{i = 0}^k f_i$$ 显然,这个东西是可以倍增的,即 $$h_{2k} = h_k + f_k * h_k$$ 那么求出所有 $h_{2^i}$ 和 $f_{2^i}$,这部分是 $O(n \log k)$ 的。 再对 $k$ 进行二进制数位 dp 即可,不难发现,这部分也是 $O(n \log k)$ 的。 主要代码如下 ```cpp void solve() { for (int i = 0; i < Nn; ++ i) cur[i] = 1; for (int i = 1; i <= m; ++ i) g[i] = 1; fft(g); memcpy(f[0], g, sizeof g); memcpy(h[0], g, sizeof g); for (int i = 1; i < 14; ++ i) { for (int j = 0; j < Nn; ++ j) f[i][j] = 1ll * f[i - 1][j] * f[i - 1][j] % mod; for (int j = 0; j < Nn; ++ j) h[i][j] = (h[i - 1][j] + 1ll * h[i - 1][j] * f[i - 1][j]) % mod; } for (int i = 14; ~i; -- i) { if (k >> i & 1) { for (int j = 0; j < Nn; ++ j) qx[j] = (qx[j] + 1ll * cur[j] * h[i][j]) % mod; for (int j = 0; j < Nn; ++ j) cur[j] = 1ll * cur[j] * f[i][j] % mod; } } fft(qx, 0); qx[0] = 1; } ```