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;
}
posted @ 2023-07-14 23:39  wangzhongyuan  阅读(6)  评论(0编辑  收藏  举报  来源