아래 풀이의 오류 등을 찾았을 경우 디스코드 0prime0으로 연락 주세요.
현재 체력을 h라고 하자. 최대한의 공격을 버틸 수 있는 전략은 다음과 같다.
- 공격을 받는다. 즉, h←h−A를 수행한다.
- h≤A이고 실크가 남아있다면 회복한다. 즉,
- h>A가 될 때까지 h←h+B를 수행한다.
- h≥H이면 h←H를 수행한다.
H≤A인 경우, 한 번의 공격에 즉사하므로 답은 항상 1이다.
H≥A+B인 경우, 회복량을 항상 B가 되도록 할 수 있다. 따라서 답은 ⌈AH+BS⌉이다.
이제 A<H<A+B인 경우만 고려하면 된다.
회복 과정 (1)을 끝낸 후에는 항상 A<h≤A+B가 된다는 것에 주목하자. y=A+B−h로 정의하면 초기값은 y0=A+B−H가 되고, 위 전략을 y에 대한 식으로 쓰면 아래와 동치이다.
- y←(y+A)modB
- y≤y0이면 y←y0
y←y0이 수행되면 체력은 초기 상태인 최대 체력으로 돌아온다. 즉, y=y0에서 시작하여 처음으로 y=y0로 돌아올 때까지 y값의 변화는 한 주기를 형성한다. 한 주기 동안 받은 공격의 수를 x라고 하면, x는 (y0+Ax)modB≤y0를 만족하는 최소의 양의 정수가 된다. 먼저, 다음과 같은 표기법을 정의하자.
(L≤x≤R)modM⇔{xmodM∈[LmodM,RmodM]xmodM∈[LmodM,M)∪[0,RmodM](LmodM≤RmodM)(LmodM>RmodM)
즉, x는 (−y0≤Ax≤0)modB를 만족하는 최소의 양의 정수이다. x=1+x′로 쓰면, x′는 (−y0−A≤Ax≤−A)modB를 만족하는 최소의 음이 아닌 정수이다. 이러한 문제는 O(logB)에 풀 수 있음이 알려져 있으며, 예를 들어 이 블로그와 같은 글에서 설명하고 있다.
f(A,M,L,R)을 (L≤Ax≤R)modM을 만족하는 최소의 음이 아닌 정수 x로 정의하자. 만약 (L>R)modM이거나 LmodM=0이면, f(A,M,L,R)=0이다.
만약 2(AmodM)>M인 경우, 부호를 뒤집어서 (−R≤−Ax≤−L)modM을 풀자. 즉, f(AmodM,M,L,R)=f(−AmodM,M,−R,−L)이다. 그러면 2(−AmodM)≤M을 만족하게 된다. 따라서 이제부터 항상 2A≤M을 가정할 수 있다.
먼저 자명한 해가 있는지 확인하자. (L′,R′)=(L,R)modM으로 두자. 만약 L′≤Ax≤R′을 만족하는 음이 아닌 정수 x가 있다면, x=⌈AL′⌉이 해가 된다.
그렇지 않다면, L′+Mt≤Ax≤R′+Mt인 x가 존재하는 최소의 음이 아닌 정수 t를 찾아야 한다. 이는 L′≤Ax−Mt≤R′과 동치이고, 이를 (modA)에서 보면 (L′≤−Mt≤R′)modA를 만족하는 해를 찾는 것이다. 이렇게 t를 찾았으면, x는 L′+Mt≤Ax를 만족하는 최소의 음이 아닌 정수이다. 즉, f(A,M,L,R)=⌈AL+Mf(−M,A,L′,R′)⌉이다. 이 관계식으로부터 f를 계산할 때 항상 2A≤M을 만족하므로, mod 값은 2배 이상 감소한다. 따라서 f(A,M,L,R)의 계산에는 O(logM)의 시간이 소요된다.
위 방법으로 한 주기 동안 받은 공격 횟수를 계산하면 x=1+f(A,B,−y0−A,−A)이고, 그 동안의 회복 횟수 N=⌈BAx⌉이다.
S를 N으로 나눈 몫을 q, 나머지를 r이라고 하자. 그러면 q주기를 반복하면서 qx번의 공격을 받고, 나머지 r번의 회복은 모두 최댓값인 B로 사용할 수 있다. 따라서 답은 n=qx+⌈AH+Br⌉이고, 시간 복잡도는 테스트 케이스당 O(logB)이다.