CF1832E
众所周知,有如下组合恒等式(由定义证明即可):
$$\dbinom{n}{m} = \dbinom{n - 1}{m - 1} + \dbinom{n - 1}{m}$$
那么令 $f_{p, i} = \sum_{j=1}^i \dbinom{i - j + 1}{p}\times a_j$,由上述恒等式可得转移方程:
$$f_{p, i} = \sum_{j=1}^i\dbinom{i - j}{p}\times a_j + \dbinom{i - j}{p - 1}\times a_j = f_{p - 1, i - 1} + f_{p, i - 1}$$
由 $f$ 的定义,得到转移式子的初始化为:
$$f_{1, i} = \sum_{j=1}^i(i - j + 1)\times a_j$$
用一个前缀和优化即可,剩下直接暴力转移,复杂度 $O(nk)$。
由于本蒟蒻觉得空间会炸,所以用了滚动数组,具体见代码。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e7 + 10;
const int mod = 998244353;
int a[N], s[N], f[2][N];
signed main() {
int n, x, y, m, k; scanf ("%lld%lld%lld%lld%lld%lld", &n, &a[1], &x, &y, &m, &k);
for (int i = 2; i <= n; ++i) a[i] = (1ll * a[i - 1] * x % m + y) % m;
for (int i = 1; i <= n; ++i) s[i] = (s[i - 1] + a[i]) % mod, f[0][i] = (f[0][i - 1] + s[i]) % mod;
int flag = 1;
for (int p = 2; p <= k; ++p) {
for (int i = 1; i <= n; ++i) f[flag][i] = (f[flag][i - 1] + f[flag ^ 1][i - 1]) % mod; flag ^= 1;
} flag ^= 1;
for (int i = 1; i <= n; ++i) f[flag][i] = 1ll * f[flag][i] * i;
long long ans = 0;
for (int i = 1; i <= n; ++i) ans ^= f[flag][i];
printf ("%lld\n", ans);
return 0;
}