题目地址
https://codeforces.com/problemset/problem/1832/E
题目抽象
给 n, a 1 a_1 a1,x,y,m,k 六个整数,需要进行如下4步操作
- 根据 a i = ( a i − 1 ⋅ x + y ) % m , i ∈ [ 2 , n ] a_i=(a_{i-1}\cdot x + y) \% m, i\in[2,n] ai=(ai−1⋅x+y)%m,i∈[2,n] 生成数组a
- 根据 b i = ( ∑ j = 1 i ( C i − j + 1 k ⋅ a j ) ) % 998244353 b_i = (\sum_{j=1}^i(C_{i-j+1}^k\cdot a_j)) \% 998244353 bi=(∑j=1i(Ci−j+1k⋅aj))%998244353 生成数组b
- 根据 c i = b i ⋅ i c_i = b_i\cdot i ci=bi⋅i 生成数组c
- 计算 c 1 ⊕ c 2 ⊕ ⋯ ⊕ c n c_1 \oplus c_2 \oplus \cdots \oplus c_n c1⊕c2⊕⋯⊕cn 的结果( ⊕ \oplus ⊕ 代表位运算的异或操作)
数据量:
1
≤
n
≤
1
0
7
1\le n\le 10^7
1≤n≤107
0
≤
a
1
,
x
,
y
,
≤
m
0\le a_1,x,y,\le m
0≤a1,x,y,≤m
2
≤
m
≤
998244353
2\le m \le 998244353
2≤m≤998244353
1
≤
k
≤
5
1\le k \le 5
1≤k≤5
题目类型
数学推导
解题思路
第1,3,4步都是非常直观,一直模拟直接计算出来
主要难点就是第二步,根据a计算b
下面进行拆解分析:
粗暴地计算每个
b
i
b_i
bi 的复杂度非常高,由于n最大可能是
1
0
7
10^7
107,需要找一个方式可以让
b
i
b_i
bi 的计算可以在
O
(
1
)
O(1)
O(1) 的时间内完成
tips:
一般这种情况都是寻找 b i b_i bi 和 b i − 1 b_{i-1} bi−1的关系,使得 b i b_i bi 可以通过 b i − 1 b_{i-1} bi−1 快速得出
而找他们的关系,就是将他们展开,然后相减,大部分情况都适用
我们将其展开,然后相减来得出其关系
b
i
=
C
i
k
⋅
a
1
+
C
i
−
1
k
⋅
a
2
…
C
2
k
⋅
a
i
−
1
+
C
1
k
⋅
a
i
b
i
−
1
=
C
i
−
1
k
⋅
a
1
+
C
i
−
2
k
⋅
a
2
…
C
1
k
⋅
a
i
−
1
b
i
−
b
i
−
1
=
(
C
i
k
−
C
i
−
1
k
)
⋅
a
1
+
(
C
i
−
1
k
−
C
i
−
2
k
)
⋅
a
2
…
(
C
2
k
−
C
1
k
)
⋅
a
i
−
1
+
C
1
k
⋅
a
i
\begin{array}{clcr} b_i&=&C_i^k\cdot a_1 &+ &C_{i-1}^k\cdot a_2 &\dots &C_2^k\cdot a_{i-1} &+ &C_1^k\cdot a_i \\ b_{i-1}&=&C_{i-1}^k\cdot a_1 &+ &C_{i-2}^k\cdot a_2 &\dots &C_1^k\cdot a_{i-1} \\ b_i-b_{i-1} &=&(C_i^k-C_{i-1}^k)\cdot a_1&+&(C_{i-1}^k-C_{i-2}^k)\cdot a_2&\dots &(C_2^k-C_1^k)\cdot a_{i-1} &+ &C_1^k\cdot a_i \\ \end{array}
bibi−1bi−bi−1===Cik⋅a1Ci−1k⋅a1(Cik−Ci−1k)⋅a1+++Ci−1k⋅a2Ci−2k⋅a2(Ci−1k−Ci−2k)⋅a2………C2k⋅ai−1C1k⋅ai−1(C2k−C1k)⋅ai−1++C1k⋅aiC1k⋅ai
∵
\because
∵ 组合数有这个性质
C
i
k
=
C
i
k
−
1
+
C
i
−
1
k
−
1
C_i^k=C_i^{k-1}+C_{i-1}^{k-1}
Cik=Cik−1+Ci−1k−1
∴
b
i
−
b
i
−
1
=
(
C
i
−
1
k
−
1
⋅
a
i
+
…
C
1
k
−
1
⋅
a
i
−
1
)
+
C
1
k
⋅
a
i
\therefore b_i-b_{i-1} = (C_{i-1}^{k-1}\cdot a_i + \dots C_1^{k-1}\cdot a_{i-1}) + C_1^k\cdot a_i
∴bi−bi−1=(Ci−1k−1⋅ai+…C1k−1⋅ai−1)+C1k⋅ai
括号里边的内容是不是很眼熟,和
b
i
−
1
b_{i-1}
bi−1非常的像,就是当k为k-1时候的
b
i
−
1
b_{i-1}
bi−1
我们将b扩展一维,原本的
b
i
b_i
bi用
b
k
,
i
b_{k,i}
bk,i代替,那么就得到
b
k
,
i
−
b
k
,
i
−
1
=
b
k
−
1
,
i
−
1
+
C
1
k
⋅
a
i
b_{k,i}-b_{k,i-1} = b_{k-1,i-1} + C_1^k\cdot a_i
bk,i−bk,i−1=bk−1,i−1+C1k⋅ai
∴
b
k
,
i
=
b
k
,
i
−
1
+
b
k
−
1
,
i
−
1
+
C
1
k
⋅
a
i
\therefore b_{k,i} =b_{k,i-1}+ b_{k-1,i-1} + C_1^k\cdot a_i
∴bk,i=bk,i−1+bk−1,i−1+C1k⋅ai
所以,我们值需要计算出
b
0
,
i
b_{0,i}
b0,i和
b
k
,
0
b_{k,0}
bk,0,剩余的
b
k
,
i
b_{k,i}
bk,i就能通过前序已经计算出的结果得到
根据定义可得
b
0
,
i
=
a
i
+
a
i
−
1
+
…
a
1
=
b
k
,
i
−
1
+
a
i
b_{0,i}=a_i+a_{i-1}+\dots a_1=b_{k,i-1}+a_i
b0,i=ai+ai−1+…a1=bk,i−1+ai
b
k
,
0
=
0
b_{k,0}=0
bk,0=0
再根据
b
k
,
i
=
b
k
,
i
−
1
+
b
k
−
1
,
i
−
1
+
C
1
k
⋅
a
i
b_{k,i} =b_{k,i-1}+ b_{k-1,i-1} + C_1^k\cdot a_i
bk,i=bk,i−1+bk−1,i−1+C1k⋅ai (当k=1时,
C
1
k
=
1
C_1^k=1
C1k=1,其他情况等于0) 就可以根据前置计算所得
O
(
1
)
O(1)
O(1)的复杂度计算得出
整体复杂度
O
(
n
⋅
k
)
O(n\cdot k)
O(n⋅k)
代码
#include <bits/stdc++.h>
using namespace std;
const int mod = 998244353;
long long a[10000001];
long long b[6][10000001];
int main() {
int n, x, y, m, K;
cin >> n;
cin >> a[1] >> x >> y >> m >> K;
for (int i = 2; i <= n; i ++) {
a[i] = (a[i - 1] * x + y) % m;
}
for (int i = 1; i <= n; i ++) {
b[0][i] = b[0][i-1] + a[i];
}
for (int k = 1; k <= K; k ++) {
for (int i = 1; i <= n; i ++) {
b[k][i] = (b[k][i - 1] + b[k - 1][i - 1] + (k == 1 ? a[i] : 0)) % mod;
}
}
long long ans = 0;
for (int i = 1; i <= n; i ++) {
ans ^= b[K][i] * i;
}
cout << ans << endl;
}