문제
길이가 $N$인 수열 $A_1, A_2, \cdots, A_N$이 주어진다. 다음 $Q$개의 쿼리를 수행하는 프로그램을 작성하여라.
- $1$ $l$ $r$ $x$: $l \le i \le r$에 대해, $A_i$를 $x$로 바꾼다.
- $2$ $l$ $r$ $x$: $l \le i \le r$에 대해, $A_i$를 $(A_i+x) \bmod 1\,000\,000$으로 바꾼다.
- $3$ $l$ $r$ $x$: $\left(\sum\limits_{i=l}^{r} C(A_i)^x\right) \bmod 998\,244\,353$을 출력한다.
- $4$ $l$ $r$ $x$: $l \le i \le r$에 대해 길이 $r-l+1$의 배열 $B$를 $B_{i-l+1} = A_i$로 설정한 후, $B$를 오름차순으로 정렬한다.$\left(\sum\limits_{i=1}^{r-l+1} C(i) \times (B_i)^x\right) \bmod 998\,244\,353$을 출력한다.
여기서 $C(n) = \frac{(2n)!}{n!(n+1)!}$으로 정의되는 카탈란 수이다.
이 문제의 수열과 쿼리를 생성하기 위한 $N$, $Q$, $seed$가 주어진다. 이후 각 수열과 쿼리는 유사 난수 생성기 Splitmix64로 생성된다. 각 수열과 쿼리를 만드는 방법은 다음과 같으며, 언어별 구현은 노트를 참고하여라. (C, C++, Java, Python, Rust, Ruby)
- $0$이상 $2^{64}$미만의 수 $x$에 대해 $\textrm{splitmix64}(x)$는 다음과 같이 정의된다. 여기서, $\oplus$는 비트간 배타적 논리합 (bitwise XOR), $a +_{2^{64}} b$는 $(a+b) \bmod {2^{64}}$, $a \times_{2^{64}} b$는 $(a \times b) \bmod {2^{64}}$, $a >> b$는 $\left\lfloor\frac{a}{2^b}\right\rfloor$를 의미한다.
- $x_1 = x +_{2^{64}} \textrm{9e3779b97f4a7c15}_{(16)}$
- $x_2 = (x_1 \oplus (x_1 >> 30)) \times_{2^{64}} \textrm{bf58476d1ce4e5b9}_{(16)}$
- $x_3 = (x_2 \oplus (x_2 >> 27)) \times_{2^{64}} \textrm{94d049bb133111eb}_{(16)}$
- $\textrm{splitmix64}(x) = x_3 \oplus (x_3 >> 31)$
- 수열 길이 $N+4Q+1$의 수열 $S$는 다음과 같이 정의된다.
- $S_0 = seed$
- $S_k = \textrm{splitmix64}(S_{k-1})$ $(1 \le k \le N+4Q)$
- 문제에서 주어지는 수열 $A$는 다음과 같이 주어진다. $(1 \le i \le N)$
- $A_i = S_i \bmod 1\,000\,000 + 1$
- 문제에서 주어지는 $j$번째 쿼리 $t_j$ $l_j$ $r_j$ $x_j$는 다음과 같이 주어진다. $(1 \le j \le Q)$
- $t_j = S_{N + 4(j-1) + 1} \bmod 4 + 1$
- $l'_j = S_{N + 4(j-1) + 2} \bmod N + 1$
- $r'_j = S_{N + 4(j-1) + 3} \bmod N + 1$
- $l_j = \min(l'_j, r'_j)$
- $r_j = \max(l'_j, r'_j)$
- $m'_j = \begin{cases} 1\,000\,000 & t_j \le 2 \\ 998\,244\,353 & t_j \ge 3 \end{cases}$
- $x_j = S_{N + 4(j-1) + 4} \bmod m'_j + 1$
입력
첫 번째 줄에 공백으로 구분된 세 정수 $N, Q, seed$가 주어진다. $(2 \le N \le 10^5;$ $1 \le Q \le 10^5;$ $1 \le seed \le 10^{18})$
문제의 방법으로 수열과 쿼리를 생성했을 때 $t_j$가 $3$ 혹은 $4$인 쿼리가 $1$개 이상 주어짐이 보장된다.
출력
$t_j$가 $3, 4$인 쿼리에 대해, 계산된 값을 한 줄에 하나씩 출력한다.
예제 입력 1
5 7 1234567891011121
예제 출력 1
69857618 553213141 174991376 892725649
이 예제에서 사용된 수열 $A$는 다음과 같다.
$A = [265\,283, 232\,568, 326\,146, 24\,477, 150\,555]$
이 예제에 사용된 쿼리는 다음과 같다.
- $[(t, l, r, op)]_{[1, 7]} = [$
- $(3, 1, 2, 615\,491\,239),$
- $(3, 5, 5, 299\,645\,653),$
- $(2, 1, 2, 307\,599),$
- $(1, 1, 1, 177\,232),$
- $(2, 3, 5, 263\,956),$
- $(3, 1, 2, 652\,234\,517),$
- $(3, 3, 5, 593\,349\,717)$
- $]$
예제 입력 2
5 7 2025
예제 출력 2
957172995 391405023 582105817 782813783 527493019
이 예제에서 사용된 수열 $A$는 다음과 같다.
$A = [100\,216, 914\,117, 715\,218, 727\,500, 443\,111]$
이 예제에 사용된 쿼리는 다음과 같다.
- $[(t, l, r, op)]_{[1, 7]} = [$
- $(4, 3, 5, 576\,065\,968),$
- $(3, 3, 4, 687\,446\,607),$
- $(2, 2, 3, 512\,403),$
- $(4, 2, 4, 396\,905\,446),$
- $(3, 5, 5, 470\,999\,508),$
- $(1, 3, 4, 312\,115),$
- $(4, 1, 4, 510\,424\,622)$
- $]$
노트
다음은 각 언어별로 문제의 데이터 생성 방법을 구현한 파일이다.
- C: splitmix64.c (C99)
- 문제에 주어진 $N$, $Q$, $seed$를 사용해서
generate(int32_t N, int32_t Q, uint64_t seed)를 호출한다. - 호출한 결과
d에 대해 $A_i$는d.arr[i]에, $t_j, l_j, r_j, x_j$은d.query[j][0],d.query[j][1],d.query[j][2],d.query[j][3]에 저장되어 있다.d의 타입은data, 각 정수의 타입은int32_t이며,d.arr[0]혹은d.query[0]은 문제의 수열 혹은 쿼리를 저장하고 있지 않음에 유의하여라.
- 호출한 결과
d에 대해 메모리를 해제하기 위해서는free_data(d)를 호출한다.
- 문제에 주어진 $N$, $Q$, $seed$를 사용해서
- C++: splitmix64.cpp (C++14, C++17, C++20, C++23, C++26, C++17 (Clang), C++20 (Clang))
- 문제에 주어진 $N$, $Q$, $seed$를 사용해서
Generate(int32_t N, int32_t Q, uint64_t seed)를 호출한다. - 호출한 결과
d에 대해 $A_i$는d.arr[i]에, $t_j, l_j, r_j, x_j$은d.query[j][0],d.query[j][1],d.query[j][2],d.query[j][3]에 저장되어 있다.d의 타입은Data, 각 정수의 타입은int32_t이며,d.arr[0]혹은d.query[0]은 문제의 수열 혹은 쿼리를 저장하고 있지 않음에 유의하여라.
- 문제에 주어진 $N$, $Q$, $seed$를 사용해서
- Java: Splitmix64.java (Java 8, Java 8 (OpenJDK), Java 11)
- 문제에 주어진 $N$, $Q$, $seed$를 사용해서
generate(int n, int q, long seed)를 호출한다. - 호출한 결과
d에 대해 $A_i$는d.arr[i]에, $t_j, l_j, r_j, x_j$은d.query[j][0],d.query[j][1],d.query[j][2],d.query[j][3]에 저장되어 있다.d의 타입은data, 각 정수의 타입은int이며,d.arr[0]혹은d.query[0]은 문제의 수열 혹은 쿼리를 저장하고 있지 않음에 유의하여라.
- 문제에 주어진 $N$, $Q$, $seed$를 사용해서
- Python: splitmix64.py (Python 3, Pypy3)
- 문제에 주어진 $N$, $Q$, $seed$를 사용해서
generate(n: int, q: int, seed: int)를 호출한다. - 호출한 결과
d에 대해 $A_i$는d.arr[i]에, $t_j, l_j, r_j, x_j$은d.query[j][0],d.query[j][1],d.query[j][2],d.query[j][3]에 저장되어 있다.d의 타입은Data, 각 정수의 타입은int이며,d.arr[0]혹은d.query[0]은 문제의 수열 혹은 쿼리를 저장하고 있지 않음에 유의하여라.
- 문제에 주어진 $N$, $Q$, $seed$를 사용해서
- Rust: splitmix64.rs (Rust 2021)
- 문제에 주어진 $N$, $Q$, $seed$를 사용해서
generate(n: usize, q: usize, seed: u64)를 호출한다. - 호출한 결과
d에 대해 $A_i$는d.arr[i]에, $t_j, l_j, r_j, x_j$은d.query[j][0],d.query[j][1],d.query[j][2],d.query[j][3]에 저장되어 있다.d의 타입은Data, 각 정수의 타입은usize이며,d.arr[0]혹은d.query[0]은 문제의 수열 혹은 쿼리를 저장하고 있지 않음에 유의하여라.
- 문제에 주어진 $N$, $Q$, $seed$를 사용해서
- Ruby: splitmix64.rb (Ruby)
- 문제에 주어진 $N$, $Q$, $seed$를 사용해서
generate(n, q, seed)를 호출한다. n,q,seed의 타입은Integer이다.- 호출한 결과
d에 대해 $A_i$는d.arr[i]에, $t_j, l_j, r_j, x_j$은d.query[j][0],d.query[j][1],d.query[j][2],d.query[j][3]에 저장되어 있다.d의 타입은Data_, 각 정수의 타입은Integer이며,d.arr[0]혹은d.query[0]은 문제의 수열 혹은 쿼리를 저장하고 있지 않음에 유의하여라.
- 문제에 주어진 $N$, $Q$, $seed$를 사용해서
출처
Contest > BOJ User Contest > 월간 향유회 > 월간 향유회 2025. 02. Ex번
- 문제를 만든 사람: jthis
- 문제를 검수한 사람: bnb2011, cologne, utilforever