근본적으로 EGF를 생각하기 편한 구조가 되겠다. 우리가 원하는 EGF는 결국 $$ \prod_{i=1}^{k-1} \left( \sum_{j=0}^n \frac{g_{i, j}}{j!} x^j \right) $$가 된다. 여기서 $g$ 값들이 하나씩 바뀌는 것이 문제다. 모듈로가 NTT 모듈로고, 작으므로, 이 문제의 요령을 생각하자.
이제부터 적용할 모든 NTT는 다항식의 차수와 관계 없이 무조건 $2^{17}$으로 생각한다.
그러면 NTT는 다항식 $f$가 주어지면 $f(w^0)$부터 $f(w^{2^{17}-1})$을 제공한다. 단, $w=t^6$이며 $t$는 원시근.
그러니 보통 우리의 요령은 각 $k-1$개의 다항식을 NTT하고, 그 결과를 pointwise 곱한 다음 역 NTT를 얹는 것이다.
그런데 이제 다항식이 바뀐다. 다행인 점은, 쿼리마다 다항식이 $k-1$개 중 하나만 바뀌고, 조금만 바뀐다는 것이다.
애초에 바뀌는 양이 단항식 하나라서, $f$ 값을 $\mathcal{O}(2^{17})$ 시간에 바꿔줄 수 있다.
또한, 바뀐 후의 pointwise 곱 역시 해당 위치 $k-1$개의 값 중 $0$의 개수 등을 관리하면 효율적으로 계산할 수 있다.
이렇게 하면 $g$ 값이 뒤집힌 이후에도 pointwise 곱 결과가 얼마인지를 빠르게 관리할 수 있다.
이제 이 결과를 전부 합친다음, 역 NTT를 하자. 여기서 NTT가 선형사상임을 이용하였다. 이러면 끝. 나쁘지 않다.
이제부터 급수 $f(x)$의 $x^n$의 계수를 $f(x)[x^n]$이라고 표기하도록 하겠다.
이 문제도 생성함수로 접근한다. 그 근거는 convolution에 있는데, 이걸 진짜 convolution으로 생각하면 너무 힘들다.
그냥 생성함수를 생각한 후, 그 함수를 $k$승한 뒤 계수의 부분합을 구하라는 문제로 받아들이는 것이 편하다.
이제 $b_m(n)$의 생성함수를 생각하자. 이는 결국 $(1+x+x^2+ \cdots )(1+x^m+x^{2m}+\cdots) \cdots $와 같다.
그러니 이를 정리하면 $\displaystyle \prod_{t=0}^\infty \frac{1}{1-x^{m^t}}$를 얻는다. 이제 본격적인 풀이를 준비하자. 어쨌든 목표는 $\displaystyle \sum_{i=0}^n \left( \prod_{t=0}^{\infty} \frac{1}{(1-x^{m^t})^k} \right)[x^i]$가 된다.
문제를 오히려 더 어렵게 만들어보자. 다항식 $P$가 있을 때, 이런 계산을 할 수 있다. $$ \sum_{i=0}^n P(i) \cdot \left( \prod_{t=0}^{\infty} \frac{1}{(1-x^{m^t})^k} \right)[x^i] = \sum_{i=0}^n P(i) \cdot \sum_{j=0}^i \left( \frac{1}{(1-x)^{k-1}} \cdot \prod_{t=1}^{\infty} \frac{1}{(1-x^{m^t})^k} \right)[x^j] $$
이제 문제를 해결할 수 있다. 기본적으로 $a$에 대한 조건이 없다면, 이는 $n/T$, $m/T$로 가능한 값이 적다는 점을 이용해서 구간을 나누고, 각 구간에 대한 $f(T) = \sum_{g|T} (T/g) \cdot \mu(T/g)$의 부분합을 미리 전처리하여 해결할 수 있다. 이러면 쿼리 당 루트 시간에 문제를 풀 수 있다.
문제는 $a$에 대한 조건이다. 이를 위해서, 쿼리를 오프라인으로 해결하자. 쿼리를 $a$ 기준으로 정렬한다.
이제 다시 $f(T) = \sum_{g|T, g \le a } (T/g) \cdot \mu(T/g)$라고 정의하자. 이제 잘 생각해보자.
$a$가 증가하면 $a$의 배수인 $T$에 대하여 $f(T)$의 값이 변한다. 조화수열을 생각하면 변화 횟수는 많지 않다.
맨 처음의 식으로 돌아가서, 우리가 계산해야 하는 것은 결국 특정 구간에 속한 $T$에 대한 $f(T)$의 값들의 합이다.
그러니 결국 점 업데이트 + 구간 쿼리 문제가 되고, 이는 단순한 세그먼트 트리를 이용하여 해결할 수 있다.
수학 대회 기출에서 가져온 문제지만 어쨌든 좋은 문제는 맞는 것 같다. 다음 관찰을 순서대로 해야한다. 증명은 생략.
1. $S(x)$는 단사함수다. 이 문제는 Putnam 2013 A2 문제이기도 하다. 여기까지는 쉽다.
2. $S(x)$는 사실 자연수에서 소수가 아닌 자연수로 (즉 1 포함) 가는 전단사함수이다. 이건 조금 까다롭다.
3. 2를 증명하는데 중요한 관찰은 다음 사실이다. $x$가 소수가 아닌 자연수라 하자. $x = t_1 > t_2 > \cdots > t_k$가 있어 $t_1 \cdot t_2 \cdots t_k$가 제곱수가 되도록 하는 $t_k$의 최댓값을 $T(x)$라고 하자. 이 값이 잘 정의됨을 보이는 것은 어렵지 않다. 이때, $S(T(x)) = x$가 성립함을 보일 수 있다.
결국 문제는 $y$가 소수인지 판별하고, 아니면 $T(y)$를 구하는 문제가 된다. 이제 이 문제와 비슷해진다.
이 문제의 근본적인 해결 방법은 소인수의 지수들의 홀짝성을 $\mathbb{F}_2$의 벡터로 보는 것이다.
답에 대해서 이분탐색을 하자. 그러면 $m, m+1, \cdots , y-1$의 이진 벡터를 선형결합하여 $y$의 벡터를 만들 수 있는지 판별하는 문제가 된다.
이를 위해서는 가우스 소거를 할 필요가 있는데, 여기서 중요한 관찰이 하나 더 필요하다.
어쨌든 $1000$ 이상의 소수를 2개 이상 가질 수는 없다는 것이다. 그러니 모든 벡터를 $1000$ 이하 소수 200개쯤에 대한 벡터와 "내가 특별히 가지고 있는 $1000$ 이상 소수 하나 (없을 수도 있음)"으로 보는 것이 좋다. 이 관찰로 시간복잡도를 획기적으로 줄일 수 있다.
이 점을 고려하면 가우스 소거를 매우 효율적으로 할 수 있으며, std::bitset으로 최적화를 하면 문제가 해결된다.
문제에서 등장하는 수열은 OEIS에도 있는 수열로, 레퍼런스를 보면 관련 문제가 수학 잡지에도 등장한 것으로 보인다.
정말 오랜만에 rated round를 쳤다. 앳코더나 코포나 레이팅이 변하는 라운드는 2018년 초 이후로 처음이다.
문제가 조금 별로였고, 그런 라운드만 잘 치는 나는 덕분에 나쁘지 않게 대회를 쳤다.
C, A를 빠르게 해결한 것에 비해 B, D가 느렸는데, 풀이를 빠르게 찾았지만 구현에서 뇌절을 한 것이 컸다.
15분을 남겼을 때 E small을 읽고 풀려고 했는데, 손을 놓아버린 것도 아깝다. E small까지는 풀었어야 했다고 본다. ㄲㅂ
A : 어쨌든 중요한 것의 2, 5의 개수이므로 이것만 잘 따지면 된다. $cnt[a][b]$를 2가 $a$개, 5가 $b$개인 수의 개수라고 하면 된다. 중복 카운팅을 조심해서 처리하자. 파싱하는 게 가장 어렵고 귀찮은 개노잼 문제다. 예전에는 무슨 가우스 소거를 A에 내더니 뭔...
B : $S$가 $T$로 갈 수 있는 필요충분조건은, (단, $S \neq T$ 가정) 우선 당연히 $|S| > |T|$이고, $T$의 길이 $|T|-1$ suffix가 $S$의 길이 $|T|-1$ suffix와 같아야 하며, $T$의 첫 글자가 $S$의 첫 $|S|-|T|+1$개의 글자에서 존재해야 한다. 이를 기반으로, 해시를 해서 문제를 해결할 수 있다. suffix의 hash와 대응되는 prefix에 존재하는 알파벳에 대하여 카운트를 늘려주면, 이를 통해서 답을 구할 수 있다. 이를 단순하게 하면 TLE가 발생하고, 실제로 관심이 있는 해시 값인 각 문자열 $S_i$의 길이 $|S_i|-1$ suffix의 hash에 대해서만 계산하면 통과된다. 모든 문자열을 뒤집고 Trie를 써도 된다.
C : 곱셈을 덧셈으로 바꾸면 FFT가 가능할 것 같다. 이를 가능하게 하는 도구는 로그다. 근데 정수론 문제니까 그냥 로그말고 이산로그를 쓰면 된다. $P$의 값이 작으므로, 문제 없다. 원시근은 $2$를 쓰면 된다. 걍 개노잼...
D : 개인적으로는 재밌게 풀었던 문제. 더 좋은 풀이가 많은 것 같으니 한 번 확인할 필요는 있겠다. 일단 $DP[i]$를 $i$에서 위로 올라가서 $1$까지 곱한 값이라고 하고, $IV[i]$를 $DP[i]$의 잉여역수라고 하자. 그러면 우리가 구해야 하는 값은 각 $1 \le i < j \le L$에 대하여 $\frac{DP[L+i-1] \cdot DP[L+P[i]-1] \cdot DP[L+j-1] \cdot DP[L+P[j]-1]}{DP[LCA(L+i-1, L+j-1)] \cdot DP[LCA(L+i-1, L+j-1)/2] \cdot DP[LCA(L+P[i]-1, L+P[j]-1)] \cdot DP[LCA(L+P[i]-1, L+P[j]-1)/2]}$를 합한 값이다. 식이 어마어마하게 더러운데, 천천히 생각해보자. 우선 $i$를 고정하고, $LCA(L+i-1, L+j-1)$을 고정해보자. 이렇게 되면 가능한 $j$의 영역이 구간을 이루게 된다. 우리가 여기서 걱정해야 하는 것은 $DP[L+j-1] \cdot DP[L+P[j]-1]$의 값과, $LCA(L+P[i]-1, L+P[j]-1)$의 위치이다. 그런데 $LCA(L+P[i]-1, L+P[j]-1)$의 위치를 고정하면, 원하는 $P[j]$의 위치도 일종의 구간이 된다. 그러니 결국 "$j$의 구간, $P[j]$의 구간이 주어졌을 때 그 안에서 $DP[L+j-1] \cdot DP[L+P[j]-1]$의 합을 구하라"는 문제가 된다. 이는 Persistent Segment Tree로 할 수 있다. 이러면 $2^H H^3$ 풀이가 완성되는데, 이를 최적화할 수 있다. 아까도 말했지만 $P[j]$의 구간에 따라서 LCA의 위치가 달라지는데, 이 구간이 이진트리 특성상 어마어마하게 깔끔하다. 그래서 사실 PST를 위에서부터 내려가는 것으로 $P[j]$의 구간에 따른 각 쿼리를 로그 시간에 전부 해결할 수 있다. 그래서 $H$ 하나가 빠지고 $2^H H^2$ 풀이가 나온다. 끝. 나의 경우 PST의 초기 크기를 단순히 $2^{17}$로 잡지 않고, $2^{H-1}$로 정확하게 잡는 것이 중요했다. 이걸 놓쳐서 디버깅이 힘들었다. 다이아 5 ~ 다이아 4 정도 되는 문제 같은데 그래도 시간 안에 해결했다는 점은 긍정적이다.
E : 재밌어 보이는 문제인데, 먼 미래에 업솔빙을 하는 것으로...
출처는 잘 모르는 문제.
입력으로는 $a, N$이 주어지며, 이때 $1 \le x \le y \le N$, $\text{gcd}(x, y)=1$, $x|y^2+a$, $y|x^2+a$를 만족하는 $(x, y)$의 개수를 구해야 한다.
$1 \le a \le 10^5$, $1 \le N \le 10^{18}$. 테케는 총 $10^6$개가 있으며, 전부 5초 내에 해결해야 한다. 메모리 제한은 256MB.
우선 $x|y^2+a$, $y|x^2+a$란 조건은 $\text{gcd}(x, y)=1$과 함께 생각했을 때, $xy|(x^2+y^2+a)$라는 것으로 바꿀 수 있다.
이제 이는 수학 올림피아드 계에서는 유명한 비에타 점핑 테크닉을 쓸 수 있는 문제가 된다.
$x^2+y^2+a=kxy$가 성립한다고 하고, 이를 만족하는 $x+y$가 가장 작은 순서쌍 $(u, v)$를 생각하자. WLOG, $u \ge v$다.
그런데 생각해보면 $(u, v)$가 조건을 만족하면, $(kv-u, v)$ 역시 조건을 만족하고, 이때 $kv-u = (v^2+a)/u$다.
그런데 최소성의 조건에서 $(v^2+a)/u \ge u$가 성립하고, $v^2+a \ge u^2$을 얻는다.
즉, $x^2+y^2+a=kxy$를 만족함과 동시에 $y^2 \le x^2 \le y^2+a$를 만족하는 $(x, y)$를 전부 구하면, 이 해들이 "기본해"가 된다.
이는 $a \le 10^5$이므로 약수를 전처리하고 lower bound 등을 잘 활용하는 것으로 후보군을 줄여서 잘 계산할 수 있다.
이제 이 "기본해"를 가지고 각 $a$에 대한 해를 전부 생성하고, std::vector에 저장하자.
쿼리에 대답하는 것은 간단한 lower bound로 해결할 수 있다. 시간/메모리가 모두 빡빡해서 조심히 구현해야 한다.
그러니 $\lfloor n/T \rfloor$, $\lfloor m/T \rfloor$가 가질 수 있는 구간의 개수가 적다는 점을 이용하여, 각 구간에 대한 $\phi$ 함수의 합을 차례대로 구해주면 충분하다. 이는 $f(x) = \phi(x)$, $g(x) = 1$, $(f * g)(x) = x$를 이용한 xudyh's sieve로 가능하다. 다른 식들도 마찬가지 방법으로 정리가 가능하고, 결국 $x \phi(x)$, $x^2 \phi(x)$의 부분합을 구하는 문제로 환원된다. 이들 역시 마찬가지 방법으로 xudyh's sieve를 사용하여 해결할 수 있다. 나름 전형적인 듯.
우선 각 $m$에 대하여 답을 구한 다음 부분합을 취하면 되는 형태다. 아예 다 구하고 출력만 하라는 뜻이다.
또한, 각 $m$에 대한 답은 자명하게 (중국인의 나머지 정리) multiplicative 하다. 그러니 prime power에 대해서만 해결하자.
이 prime power가 홀수인 경우, 문제는 어렵지 않다. $(x+y)^2 \equiv a+2b$, $(x-y)^2 \equiv a-2b$이므로 $a+2b$, $a-2b$는 이차잉여이고, 역으로 이 조건만 만족하면 조건을 만족하는 $x, y$도 있기 때문이다. 그러므로 답은 해당 prime power에 대한 이차잉여의 개수를 제곱한 것이다.
prime power가 2의 거듭제곱인 경우 상황은 조금 복잡하다. 작은 거듭제곱의 경우 brute force로 답을 구할 수 있고, 믿음의 Berlekamp-Massey 알고리즘으로 답을 전처리할 수 있다. 아예 하드코딩해도 된다. 이제 이를 합쳐서 답을 구하는 것은 쉽다. 벌레캠프 각을 너무 늦게 봐서 해결이 오래 걸렸다.
Hackenbush에 대한 간단한 튜토리얼을 쓰려고 하는데, 내가 이걸 잘 아는 거는 아니라서 (...) 증명 및 깊이 있는 이론들은 (ordinal 등장 등) 대부분 생략하고 알고리즘 문제 풀이에 써먹을 수 있는 부분들만 간략히 추려서 쓰려고 한다. 자세한 증명은 구글에 검색하면 자료가 매우 많으니 찾아보는 것을 추천한다 :)
Hackenbush 게임은 두 명이서 하는 게임으로, 여러 가지 버전들이 존재하지만 근본적인 목표는 똑같다.
위 그림과 같이, 일종의 그래프가 지면에 연결되어 있는 상태에서 게임이 시작된다.
각 플레이어는 순서대로 간선 하나를 제거하는데, 이때 더 이상 지면에 연결되지 않게 되는 간선들은 모두 삭제된다.
일반적인 룰에서는 (normal play convention) 간선을 제거하지 못하게 되는 플레이어가 패배한다.
간선이 무한히 많은 경우도 존재하지만, 여기에서는 유한한 개수의 간선이 존재한다고 가정한다.
그러면 게임이 확실하게 Sprague-Grundy 방식으로 분석이 가능해진다. 이를 위해서 다음 Principle을 활용한다.
Colon Principle: 그래프 $G, H, K$가 있다. $H, K$의 Grundy 값이 같다면, $G$의 정점 $x$에 $H$를 붙인 그래프와 $x$에 $K$를 붙인 그래프의 Grundy 값이 동일하다. 그러므로, 한 점에서 '가지치기'가 되는 그래프가 있다면, 각 가지들의 Grundy 값의 XOR에 해당하는 길이의 일직선을 붙이는 것으로 가지들을 대체할 수 있다. 이를 통해서 트리 그래프에 대한 분석을 끝낼 수 있다. DFS를 돌면서 서브트리의 Grundy 값을 순서대로 계산하면 된다.
Fusion Principle: 두 정점이 한 사이클 위에 놓인다면 (지면을 하나의 노드로 본다) 두 점을 하나로 합쳐도 Grundy 값이 변하지 않는다.
이때 두 점을 잇는 간선들은 self-loop가 된다. 이 성질을 이용하면, 임의의 그래프에 대한 Grundy 값을 구할 수 있다.
실제로 이를 활용하는 문제는 본 적이 없지만, 아무튼 이를 이용하면 기본 Hackenbush에 대한 분석은 끝이다.
연습문제: Project Euler 400 Fibonacci Tree Game, BOJ 13893 Dictionary Game
두 문제 다 Hackenbush에 대한 이해와 적당한 구현을 (DP/Trie 등) 통해서 해결할 수 있다. Fusion Principle은 필요 없다.
Blue-Red Hackenbush는 조금 색다르다. 이제는 각 간선마다 누가 자를 수 있는지가 둘 중 한 명으로 정해져 있다.
각 플레이어를 Blue/Red라고 하고, Blue 간선은 Blue만, Red 간선은 Red만 자를 수 있도록 한다.
이때는 각 연결 컴포넌트 $G$에 대하여, 그 컴포넌트의 값 $v(G)$를 다음과 같이 재귀적으로 정할 수 있다.
아무것도 없는 그래프의 경우 값은 자명하게 $0$이다. $G$가 nonempty라고 가정하자.
$b$를 Blue가 만들 수 있는 상태 $G'$ 중 $v(G')$의 최댓값이라 하자. 불가능한 경우 $-\infty$.
$r$을 Red가 만들 수 있는 상태 $G'$ 중 $v(G')$의 최솟값이라 하자. 불가능한 경우 $\infty$.
만약 $b < n < r$인 정수 $n$이 존재한다면, $v(G)$는 해당하는 정수 $n$ 중 $0$에 가장 가까운 것이다.
그렇지 않다면, $v(G)$는 $b < x < r$을 만족하는 유리수 $x$ 중 분모가 $2$의 거듭제곱인 것 중에서 분모가 최소인 것이다.
또한, 독립적인 그래프 $G, H$에 대하여 $v(G+H) = v(G) + v(H)$가 성립한다.
만약 $v(G) > 0$이라면 Blue가 승리, $v(G) < 0$이라면 Red가 승리, $v(G)= 0$이라면 후공 승리가 된다.
이 게임에 대한 직관적인 이해를 원한다면 stonejjun의 블로그를 찾아보는 것을 추천한다.
이걸 모두 짬뽕한 Blue-Red-Green Hackenbush도 있는데, 이건 진짜 무서워 보인다 ㅋㅋ
연습문제: BOJ 13409 Black and White Boxes, BOJ 18945 조직된 ㄱ폭탄 게임
13409는 Hackenbush 값을 계산한 다음 Meet In The Middle을 하면 간단하게 해결할 수 있다.
18945는 몇 가지 관찰을 한 다음, 문제를 Blue-Red Hackenbush로 변형하여 해결할 수 있다.
이 글의 진짜 목적 중 하나가 18945의 풀이를 적는 것이니, 여기에 소개한다.
각 게임을 독립적인 Blue-Red Hackenbush 게임으로 보고, 그에 대응하는 값을 계산하자.
그러면 남은 쿼리들은 전부 단순한 point update range query 문제가 되므로, 펜윅/세그먼트 트리를 이용하여 계산할 수 있다.
그러니 문제 난이도의 99%는 각 게임을 Blue-Red Hackenbush 게임으로 변환하는 것에서 나온다.
일반성을 잃지 않고 A 폭탄이 하나 존재한다고 가정하자. 그러면 B 폭탄을 3가지 종류로 나눌 수 있다.
종류 1: A 폭탄이 터지면 강제로 제거되는 B 폭탄들
종류 2: 터뜨리면 A 폭탄이 터지게 되는 B 폭탄들
종류 3: A 폭탄과 서로 interact 할 수 없는 (즉, 하나가 터져도 다른 하나가 터지지 않음) B 폭탄들
이 게임판에서 A가 할 수 있는 행동은 단순히 A 폭탄 하나를 터뜨리는 것 뿐이다.
B가 할 수 있는 행동은 다양한데, 실제로 고려해야 하는 것은 몇 가지 없음을 알 수 있다.
우선 종류 3의 폭탄과 같은 경우에는 애초에 A 폭탄이 터지던 말던 상관이 없기 때문에, 최대한 마지막에 터뜨리는 것이 좋다.
물론, 자신이 터뜨린 폭탄에 의해 자신의 다른 B 폭탄이 쓸데없이 터지지 않도록 순서를 잘 정해서 터뜨려야 한다.
종류 2의 폭탄은 터뜨린다면 강제적으로 종류 1의 폭탄 중 남아있는 것은 무조건 터지게되며, 경우에 따라서 종류 3의 폭탄 역시 터질 수 있다.
그러니 A 폭탄을 제거할 목적으로 종류 2의 폭탄을 터뜨린다면 종류 3의 폭탄을 최소한으로 터뜨리도록 하는 폭탄을 하나 찾아서 그걸 터뜨려야 한다.
종류 1의 폭탄은 터뜨린다면, 다른 종류 1의 폭탄을 터뜨리지 않도록 행/열 순서를 잘 잡아서 순서대로 터뜨려야 한다.
이를 종합하면, 다음과 같은 Blue-Red Hackenbush 그림을 그릴 수 있다. A가 Red, B가 Blue라고 하자.
그래프가 특수한 형태를 가진다. 그러니, 이와 같은 경우에서 Hackenbush 값은 아예 closed form 식을 통해서도 구할 수 있다.
나는 DP를 이용하여 위에서 설명한 규칙을 직접 적용하는 방식으로 구현했다. 분수를 다루기 귀찮으니, 적당히 큰 2의 거듭제곱을 곱해줘서 다루면 편하다.
DP 식 자체는 간단하고, cost 함수인 $\displaystyle \sum_{i=1}^n \left( 1 + \lfloor \log_2 i \rfloor \right)$ 및 실제로 구하고자 하는 값이 $n$에 대하여 볼록함은 쉽게 추측할 수 있고 증명도 수학적 귀납법으로 어렵지 않다. 그런데 $n$ 범위가 $10^{15}$로 매우 높고, 아마도 출제자가 답이 long long int 범위를 넘어가도록 문제를 만들지는 않았을 것이므로, 답이 증가하는 폭이 꽤 작을 것이라고 유추할 수 있다. 즉, 실제로 답의 기울기가 변화하는 점이 적을 것이라고 생각하는 것이다. 이제 기울기가 변화하는 점을 이분탐색/삼분탐색을 잘 섞어서 찾아나가면 된다. 이 아이디어만 잡으면 그 뒤는 어렵지 않은데 아이디어 잡기가 굉장히 어려운 문제인 것 같다.
전형적인 포함-배제를 하듯이, 열심히 계수를 맞춰주면 되는데, 결론적으로 이런 식이 나온다. 검증해보자.
그러면 식이 대충 계산 가능한 다항식이 분자에 있고, $(1-x^t)$ 형태의 식이 분모에 있는 형태가 된다.
그런데 $\displaystyle \frac{1}{1-x} = 1+ x+x^2+ \cdots $를 이용하면 분모를 없애고 식 전체를 생성함수로 전개할 수 있다.
조금 머리를 굴리면, 댓글의 말처럼 뒤에 있는 네 개의 항을 $\mathcal{O}(n^3)$으로 단순 계산을 할 수 있음을 확인할 수 있다.
첫 번째 항인 $A(x)^4$가 약간의 문제가 된다. 이 경우 $\sum_{i=1}^n \left( x^{l_i} - x^{r_i+1} \right) $에 곱해지는 값은 $\displaystyle \frac{1}{(1-x)^4} = \sum_{k=0}^\infty \binom{k+3}{3} x^k$이다.
이제 $\displaystyle P(x) = \sum_{i=1}^n \left( x^{l_i} - x^{r_i+1} \right)$라 하고, 다항식 $f$의 $x^t$의 계수를 $[f]_t$라 하자.
우리가 구하고자 하는 값은 $\displaystyle \sum_{i=0}^s [P(x)^4]_i \binom{s-i+3}{3}$이다. 문제는 역시 $P(x)^4$를 구할 여력이 없다는 점이다.
이 문제를 Vandermonde's Identity로 해결할 수 있다. 우선 $\displaystyle [P(x)^4]_i = \sum_{j=0}^i [P(x)^2]_j [P(x)^2]_{i-j}$라고 써보자.
그러면 우리가 계산해야 하는 것은 $\displaystyle \sum_{i=0}^s \sum_{j=0}^i [P(x)^2]_j [P(x)^2]_{i-j} \binom{s-j-(i-j)+3}{3}$이다.
이제 저 이항 계수를 쪼개고 싶다는 게 명확해지고, $\displaystyle \binom{s-j-(i-j)+3}{3} = \sum_{l=0}^3 \binom{3-j}{l} \cdot \binom{s-(i-j)}{3-l}$로 이를 쪼갤 수 있다.
식을 제대로 쪼개고 나면 문제가 크게 어렵지 않다. $P(x)^2$에 대한 정보를 전부 계산하고, 정렬/부분합이면 된다.
은근 상수도 커서 (특히 $\mathcal{O}(n^3)$ 부분이 조금 상수가 크다) 구현을 나름 섬세하게 해야 했다.
정말 재밌게 푼 문제다. 깔끔하고 아이디어도 좋은 문제. 이 문제는 풀이만 써놓기엔 좀 애매해서 생각 과정도 적는다.
Part 1: 기본적인 관찰
결국 문제의 statement는 각 문제에 대한 아이디어는 시작 후 $0, 1, \cdots t-1$분 후 중 한 시각에 얻어지고, 각 확률이 $1/t$로 동일하며 이는 문제마다 독립적이라는 것이다. 이는 $p \cdot t^n$이 정수인 이유가 되고, 동시에 이 문제가 확률 문제가 아닌 카운팅 문제임을 시사한다.
Part 2: $n$이 작은 경우 직접 계산
우선 $x_1+x_2+ \cdots + x_n > t$인 경우에 답이 $0$임은 자명하다. $n=1$인 경우 답이 $t-x_1+1$임도 자명하다.
$n=2$인 경우를 열심히 계산했고, (이 계산은 어렵지 않다) $(t-x_1-x_2+1)(t-x_2+2)$를 얻었다.
이는 문제의 답이 생각보다 간단한 형태를 가질 거라는 믿음을 나한테 줬다. 도움이 꽤 된듯.
Part 3: $n = t$, $x_1 = x_2 = \cdots = x_n = 1$인 경우
예제 2가 이런 경우고, $n=5$였다. 이때 예제 답이 $1296$이었는데, 이건 $6^4$다.
뭔가 느낌이 쎄해서 $n=2$, $n=3$인 경우를 손으로 계산했는데, 각각 $3^1$, $4^2$가 나왔다.
여기서 나는 답이 $(n+1)^{n-1}$이라고 확신했고, 증명을 고민하기 시작했다. 근데 생각해보니 아는 내용이었다.
이 경우에는 중간에 문제가 바뀌는 걸 고민할 필요가 없다. 시간 안에 아이디어가 공급되는 것만이 중요하다.
각 문제의 아이디어가 나오는 시간을 $t_0, t_1, \cdots , t_{n-1}$이라 하면, 정렬 후 $i$번째 값이 $i$ 이하이면 된다. (0-index)
예전에 $\mathcal{O}(n^2)$ 논문이 있길래 이걸 구현해보려다가 뇌절을 심하게 하고 멘탈 나가서 놓은 문제였다.
풀이는 이 블로그에서도 언급한 EGZ 정리의 증명을 이용한다. 우선 합성수인 경우, 문제를 쪼개서 합칠 수 있다.
$n=ab$라 쓰자. 단, $a, b > 1$. $2ab-1$개의 수가 있을 때, $a$에 대한 문제를 여러 번 풀어 합이 $a$의 배수가 되도록 묶인 $2b-1$개의 그룹으로 만들 수 있다. $2a-1$개의 수를 가지고 합이 $a$의 배수인 그룹을 하나 만들고, 사용되지 않은 수를 다시 써먹는 것을 반복하면 된다.
이제 $2b-1$개의 그룹을 가지고 단순히 $b$에 대한 문제를 풀면 된다. 이는 구현이 귀찮지만 어렵지는 않다.
여기서는 Cauchy-Davenport 정리를 사용한다. 주어진 수를 정렬하여, $0 \le a_1 \le a_2 \le \cdots \le a_{2p-1} < p$라 하자.
이제 $a_i = a_{i+p-1}$인 $i$가 있다면 $i$부터 $i+p-1$을 전부 택하면 합이 자명하게 $p$의 배수가 된다.
그렇지 않다면, 주어진 수를 $\{a_1\}, \{a_2, a_{p+1}\}, \{a_3, a_{p+2}\}, \cdots, \{a_p, a_{2p-1} \}$로 분할하자.
첫 집합을 제외하면, 각 집합의 크기는 (중복 원소가 없으므로) $2$가 된다. 이제 순서대로 Cauchy-Davenport를 쓰면, 각 집합에서 한 원소를 골라서 $p$의 배수를 만들 수 있음을 얻는다. 이를 knapsack과 같은 방법으로 처리하면 끝. 참 멋진 문제라고 생각한다.
Online FFT 테크닉을 이용하여 해결할 수 있는 문제다. 여기서는 이 테크닉을 간단하게 설명한다.
배열 $a$가 주어져 있고, 이때 $c_i = \sum_{j=0}^i a_j a_{i-j}$를 구하고 싶다고 하면, 단순히 FFT를 적용하면 된다.
그런데 만약 $a_i$가 $c_i$와 관련된 값이라던가, 배열 $a$가 바로 주어지지 않고 online으로 주어지면 어떻게 될까?
이때는 단순한 FFT로는 해결하기가 어려우나, 분할 정복을 추가하여 해결할 수 있다.
여기서는 설명의 간단함을 위해 $a_0=0$이라고 가정하고, $c_i = \sum_{j=1}^i a_j a_{i-j}$를 계산해야 $a_i$를 얻을 수 있는 구조라고 생각하자.
카탈란 수의 점화식을 순수하게 FFT 하나로 계산한다고 생각하면 편할 것 같다.
$[L, R)$에 대해서, 문제를 해결하는 재귀함수 $f([L, R))$을 생각해보자. 이때 기본 가정은, 각 $L \le x < R$에 대하여 $a_0, a_1, \cdots, a_{L-1}$의 값을 이미 알고 있으며 각 $L \le t < R$에 대해 $p_L(x)^2 = \left( \sum_{i=0}^{L-1} a_i x^i \right)^2$의 $x^t$ 계수를 저장해놨다고 가정한다.
먼저 $M=(L+R)/2$를 잡고, $f([L, M))$을 호출하자. 이제 $f([M, R))$을 호출할 준비를 해보자.
현재 저장해놓은 $M \le t <R$에 대한 $p_L(x)^2$의 $x^t$의 계수들을 $p_M(x)^2$의 $x^t$의 계수들로 바꿔야 한다.
이는 결국 $(p_M(x)-p_L(x))(p_M(x)+p_L(x))$의 $x^t$ 계수를 구하는 것과 마찬가지다.
$p_M(x)-p_L(x)$는 $L$차 이상 $M$차 미만 단항식들로 구성되어 있다. 또한, 구해야 하는 계수는 최대 $R-1$차이다.
그러니, $p_M(x)+p_L(x)$의 $R-1-L$차 이하 단항식들만 고려해도 충분하다. 그러니 곱해야 하는 두 다항식의 실질적인 차수는 $R-L$에 비례한다. 개인적으로는 $L=0$인 경우를 따로 고려하는 것이 마음이 편하다. 어쨌든 정복 단계라고 볼 수 있는 스텝이 FFT로 $\mathcal{O}((R-L)\log(R-L))$에 된다.
그러니 총 시간복잡도는 $\mathcal{O}(N \log^2 N)$이 된다. 로그 하나는 순수한 분할정복에서 나오므로 꽤 빠르다.
이 문제와 매우 비슷한 형식을 가지고 있는 문제다. 마찬가지로 포함배제를 사용해보자. 편의상 $v_i = b^i - c + 1$이라고 쓴다.
그러면 식이 $\displaystyle \sum_{S \subset \{1,2, \cdots n\}} (-1)^{|S|} \binom{m+n-1-\sum_{i \in S} v_i}{m}$임을 쉽게 확인할 수 있다. 여기까지는 링크의 문제와 같다.
보통 이런 식이 나오면, $\sum_{i \in S} v_i$에 대한 다항식으로 이항계수를 생각하고 싶다.
그런데 여기서는 조합적 해석의 특성상, $a<b$에 대하여 $\binom{a}{b}$를 다항식의 값이 아니라 $0$으로 봐야 한다.
이걸 다루기가 꽤 까다로운데, 앞선 문제에서는 이를 meet in the middle 방식으로 해결했다.
여기서는 $v_i$의 특수한 형식 - 즉 지수적으로 증가하는 형태 - 를 극단적으로 활용할 수 있다.
$dp[i][j][k]$를 $\sum_{S \subset \{1,2, \cdots , i\}, |S|=j} \left( \sum_{t \in S} v_t \right)^k$라고 정의하자. 이는 식을 열심히 전개하여, $\mathcal{O}(m^4)$에 전처리를 할 수 있다.
이제 $\sum_{i \in S} v_i \le m+n-1$인 집합 $S$에 대해서만 다항식의 합을 계산해야 한다. 이는 Digit DP를 하듯이 계산할 수 있다.
큰 "비트"부터 내려가면서, 지금까지 뽑은 것을 봤을 때 나머지를 "자유롭게" 뽑을 수 있다면, 전처리한 DP 값을 활용하여 답을 구할 수 있다.
여기서 $v_i$의 지수적 증가를 활용한다. 전체적으로 문제는 $\mathcal{O}(m^4)$ 시간에 해결되며, 이는 PyPy3으로도 충분히 빠르게 돈다.
감동적으로 좋은 문제. 우선 많은 XOR 문제가 그렇듯이, 비트로 쪼갤 생각을 해야 한다.
$m_1 \ge m_2 \ge \cdots \ge m_n$이라고 하고, $2^t \le m_1 < 2^{t+1}$이 성립한다고 하자. 특히, $m_1$부터 $m_k$가 $2^t$ 이상이고, 나머지는 $2^t$ 미만이라고 하자.
우리는 기본적으로 $2^t$ 비트를 짝수개 뽑아야 한다. $1 \le i \le k$인 $i$에 대하여, $i$번째 변수에서 $2^t$를 뽑는다면 그 변수의 범위는 $2^t$에서 $m_i$가 된다.
그렇지 않는다면, $i$번째 변수는 $0$부터 $2^t-1$까지를 아무거나 뽑아줄 수 있다. 이는 굉장히 강력한 조건이며 이 문제의 핵심이다.
만약 $1 \le i \le k$ 중 $2^t$를 뽑지 않는 $i$가 있다면, 그 $i$를 제외하고 다른 변수들이 $2^t$ 비트만 제대로 맞춰주면 전체 XOR이 $0$이도록 $i$번째 변수의 값을 유일하게 결정할 수 있기 때문이다. 이를 생각하면, "처음으로 $2^t$를 뽑지 않는 index $i$"를 기준으로 카운팅을 해서 답을 얻을 수 있다.
만약 모든 $1 \le i \le k$에 대하여 $2^t$를 뽑는다면, $k$는 짝수여야 하며, $2^t$ 비트를 모두 제거했다고 가정하고 더 작은 문제를 해결하면 된다.