✅ 한 것들
⚔️ Atcoder
E - Count A%B=C
a가 b보다 작으면 a = c이므로, 이것들은 제거 대상.
이러면 nC2의 경우의 수가 남는다. (a > b인 경우의 수)
이제 c = 0만 아니면 된다. c = 0이라는 건 a가 b로 나눠진다는 것. 이것들을 제거하면 된다.
b를 고정하면, a가 b의 배수인 경우의 수들을 제거해야 함. 즉, floor(N/b) - 1만큼이 제거 대상.
b는 1부터 N까지 가능하므로, 이 연산을 효율적으로 할 방법을 떠올려야 함.
다음의 조건을 만족하는 (l,r,q)들을 구해야 함.
- l <= b < r일 때, q = floor(N/b)이다.
- 각 q에 대해 `[l,r)`의 범위는 겹치지 않음.
이 연산은 O(sqrt(N))이다.
증명:
q <= sqrt(N)이면 q = 1부터 sqrt(N)까지 각각 하나의 (l, r, q) triple을 만들면 된다.
sqrt(N) < q이면 l은 (b의 범위의 하한은) sqrt(N)보다 작다. (몫이 크면 나누는 수도 작을 것이다.)
두 경우 각각 q 경우의 수가 O(sqrt(N)), l 경우의 수기 O(sqrt(N))이므로 최종 시간 복잡도는 O(sqrt(N))
즉, q가 같은 l <= b < r의 구간이 O(sqrt(N))이라는 뜻.
l이 1부터 시작하여
q = floor(N/l)일 때
r = floor(N/q) + 1로 계산하고,
(l,r,q)를 한 묶음으로 생각한 뒤,
r을 다시 l에 할당하여 반복하여 답을 구한다.
이해는 하긴 했다.
🎮 Frog on Lotus
로직 전환 작업
- 주석으로 적어놨던 세부 구현 사항들 거의 다 채워넣음
- ScriptableObject에 데이터만 추가하면 스테이지 추가되도록 변경
- difficulty로 적들의 이동 속도가 설정되게 하는 과정에서, 서로 다른 이동 스크립트에서 SetSpeed()를 동일하게 호출하고 싶어서 interface 사용하긴 했는데 함수 호출 묶는 거 하나 때문에 interface 만드는게 맞는지 의문이 들긴 했음. 대안이 없어서 그대로 둠.
- frogAttack에서 enemy를 죽이면 EnemyManager(싱글톤)를 호출하여 enemyList에서 enemy 삭제, 직후 StageManager(싱글톤)의 ClearCheck()를 호출하여 EnemyManager(stageManager에 의존성 주입해둠)의 AreAllEnemyDead() 호출.
- EnemyManager를 두 가지 경로로 접근하게 되는 건 책임 소재를 명확히 지정해주기 위함
- 싱글톤을 의존성 주입해놓은 건, 원래 stagemanager 아래에 enemymanager가 있는 구조였는데, enemymanager도 전역 접근이 필요해져서 싱글톤화했음. 생각해보면 싱글톤을 의존성 주입해두는 것도 단점 극복하기 위한 거니까 그대로 두는게 나쁘지 않을 것 같았음.
- 지금보다도 초보 때 작성했던 이상한 로직들 다 걷어내고 대체함
- 씬 상태 변경을 못하니까 프리팹에 UI나 Update() 달린 스크립트들 달아놓고 스폰하고 지우는 방식으로 상태를 관리했었음. State 패턴을 사용할까 하다가 과한 것 같아서 일반적인 함수 호출로 상태 변경. UI나 SoundManager같이 책임이 명확한 매니저 스크립트들이 담당한 기능들의 상태를 바꿈.
- 경계선에서만 스폰하면 되는데 도넛 모양 영역에서 스폰을 하게 해놨길래 경계선으로 바꿈.
인트로 화면에서 클릭 -> stageSO에 따라 스테이지 시작 -> 적 잡기 -> 광고 호출
까지는 완료.