P12595 出生于驾校
题目描述
扶苏有一个长度为 $n$ 的数列 $a = [a_0, a_1, \dots a_{n - 1}]$。您要帮她支持如下操作,共 $q$ 次:
- `1 x`:给数列里每个数都加上 $x$,即对 $0 \leq i < n$,都执行 $a_i := a_i + x$,其中 $:=$ 表示赋值。
- `2 x`:给数列里每个数都乘上 $x$,即对 $0 \leq i \lt n$,都执行 $a_i := a_i \times x$,其中 $:=$ 表示赋值。
- `3 k p`:对所有满足 $i \equiv p \pmod {2^k}$ 的 $i$,求 $a_i$ 的和对 $998,244,353$ 取模的结果,即求 $(\sum_{i = 0}^{n - 1} a_i \times [i \equiv p \pmod {2^k}]) \bmod 998,244,353$,其中 $[]$ 是[艾佛森括号](https://baike.baidu.com/item/%E8%89%BE%E4%BD%9B%E6%A3%AE%E6%8B%AC%E5%8F%B7)。
为了避免输出过大,你只需要输出所有操作 $3$ 的结果的**按位异或和**。
本题的输入规模非常巨大,因此我们提供了一个随机数生成器来生成数列和询问。你可以参考输入格式来具体查阅内容。
输入格式
为了避免读入过大,我们将提供如下数据生成器:
标准输入共两行,第一行有四个整数 $n, q, \mathrm{minK}, \mathrm{maxK}$。其中 $n$ 和 $q$ 表示数列长度和操作次数,$\mathrm{minK}$ 和 $\mathrm{maxK}$ 表示输入 $k$ 的最小和最大值。数据生成器将用到这两个数值。
**我们提供了 C++、Java、Python 三种语言的数据生成器参考代码,你可以在说明/提示中直接参考和使用这些代码,而无需被担心判定为作弊**。
标准输入第二行有三个参数 $X, Y, Z$,这三个参数是 **32 位无符号整型**,数据生成器将利用这三个参数生成随机数。
你应该定义如下函数:
```cpp
typedef uint32_t ui;
ui X, Y, Z;
ui nextInt(ui &x = X, ui &y = Y, ui &z = Z) {
x ^= y > (x & 31);
z ^= x > 5; y ^= y > 6;
return x;
}
```
接下来,每次调用 `nextInt()` 函数,你都将得到一个 $32$ 位无符号整数。
读入标准输入里的两行 $7$ 个整数后,你已经得到了 $n$ 和 $q$ 的值,接下来按如下代码生成数列 $a$:
```cpp
const int lim = 998'244'353;
std::vector genArr(int n) {
std::vector ret(n);
for (int i = 0; i < n; ++i) ret[i] = nextInt() % lim;
return ret;
}
```
接下来,你要生成 $q$ 次操作,对每次操作,方法如下:
- 令 `op = nextInt() % 3 + 1`
- 若 $op = 1$ 或 $op = 2$,取 `x = nextInt() % lim`
- 否则**依次**取:`k = nextInt() % (maxK - minK + 1) + minK, p = nextInt() % (1
输出格式
输出一行一个整数,表示所有操作 $3$ 的结果的按位异或和。
说明/提示
### 样例解释
调用数据生成器得到的序列 $a = [17,17301653,16795857,17320599,754976961]$;
得到的操作依次是:
```plain
2 558452929
2 832199221
1 38834385
3 0 0
3 1 1
1 818308198
2 135235876
```
### 数据规模与约定
| 测试点编号 | $n \le $ | $q \le$ | 特殊约定 |
| :-: | :-: | :-: | :-: |
| $1,2$ | $10^3$ | $10^3$ | 无 |
| $3$ | $10^5$ | $10^5$ | $k=0$ |
| $4$ | $10^5$ | $10^5$ | $k=1$ |
| $5$ | $10^5$ | $10^5$ | $k = 10$ |
| $6$ | $10^5$ | $10^5$ | 无 |
| $7$ | $10^5$ | $4 \times 10^7$ | 无 |
| $8$ | $4 \times 10^7$ | $10^5$ | 无 |
| $9, 10$ | $4 \times 10^7$ |$4 \times 10^7$ | 无 |
对全部的测试数据,保证 $1 \leq n, q \leq 4 \times 10^7$,$1 \leq op \leq 3$,$0 \leq k \leq \log_2 n$,$0 \leq p < 2^k$,$0 \leq a_i,x < 998,244,353$。
为了帮助你快速判断当前测试点的特殊约定,我们保证:编号为 $i$ 的测试点所读入的 $n$ 的末位数字为 $i \bmod 10$。
### 参考实现
【C++ 参考实现】
```cpp
#include
typedef uint32_t ui;
int n, q, minK, maxK;
ui X, Y, Z;
ui nextInt(ui &x = X, ui &y = Y, ui &z = Z) {
x ^= y > (x & 31);
z ^= x > 5; y ^= y > 6;
return x;
}
const int lim = 998'244'353;
std::vector genArr(int n) {
std::vector ret(n);
for (int i = 0; i < n; ++i) ret[i] = nextInt() % lim;
return ret;
}
int main() {
std::cin >> n >> q >> minK >> maxK;
std::cin >> X >> Y >> Z;
std::vector a = genArr(n);
for (int _ = 1; _ (x & 31);
y = maskToU32(y);
z ^= x >> 5;
x = maskToU32(x);
y ^= y >> 6;
z = maskToU32(z);
X = x;
Y = y;
Z = z;
return X;
}
private static int[] genArr(int n) {
int[] ret = new int[n];
for (int i = 0; i < n; ++i) {
ret[i] = (int)(nextInt() % lim);
}
return ret;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int q = scanner.nextInt();
int minK = scanner.nextInt();
int maxK = scanner.nextInt();
X = scanner.nextLong();
Y = scanner.nextLong();
Z = scanner.nextLong();
int[] a = genArr(n);
for (int qId = 1; qId 5)
x &= 0xFFFFFFFF
y ^= (y > 6)
z &= 0xFFFFFFFF
X, Y, Z = x, y, z
return X
n, q, minK, maxK = map(int, input().split())
X, Y, Z = map(int, input().split())
a = [nextInt() % lim for _ in range(n)]
for _ in range(q):
op = nextInt() % 3 + 1
if op == 1:
x = nextInt() % lim
#fill your code here
elif op == 2:
x = nextInt() % lim
#fill your code here
elif op == 3:
k = nextInt() % (maxK - minK + 1) + minK
p = nextInt() % (1