1. 문제
C - Four Variables (atcoder.jp)
C - Four Variables
AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.
atcoder.jp
2. 풀이1
당연히 안될 것 같지만 방법을 모르겠다면 브루트포스로 접근하는게 기본이다
AB+CD = N을 만족하는 양의 정수쌍 A,B,C,D를 찾기 위해 1부터 N까지 순회해본다
이 값을 AB = x라 하고, 그렇다면 CD는 자동으로 N-x로 결정된다
그리고 AB = x에서 1부터 x까지 순회해서 그 수를 A라 하고, 만약 x가 A로 나누어 떨어진다면 B를 찾은 것이다.
마찬가지로 CD=(N-x) = y에서 1부터 y까지 순회해서 그 수를 C라 하고, 만약 y가 C로 나누어 떨어진다면 C를 찾은 것이다.
여기서 1부터 x까지가 아니고 √x까지가 아니냐? 하지만... 그건 A > B일때이고 여기서는 A < B여도 개수를 세야하니까 x까지 순회해야한다
n = int(input())
count = 0
for x in range(1,n):
y = n-x
for a in range(1,x+1):
if x % a != 0:
continue
else:
for c in range(1,y+1):
if y % c == 0:
count += 1
print(count)
근데 O(N3)이라 어림도 없다.
3. 풀이2
조금 머리를 써서 AB = x에서 (A,B) 쌍을 세서 count1이라 하고, CD = y에서 (C,D) 쌍을 세서 count2라 하면...
count1 * count2는 AB+CD = N을 만족하는 (A,B,C,D)의 개수가 된다
n = int(input())
count1 = 0
count2 = 0
count = 0
for x in range(1,n):
y = n-x
for a in range(1,x+1):
if x % a == 0:
count1 += 1
for c in range(1,y+1):
if y % c == 0:
count2 += 1
count += (count1*count2)
count1 = 0
count2 = 0
print(count)
이러면 O(N * (N+N))이라 O(2N2)이라 조금 빨라도 여전히 느리다
4. 풀이3
더욱 머리를 써서... AB=x를 만족하는 (A,B)의 개수는 결국 x의 약수의 개수와 같다
x의 약수의 개수는 x의 (소인수 지수+1)의 곱과 같다.
따라서 1부터 n-1까지 순회해서 x를 AB라 하고 N-x를 CD라 하자.
x를 소인수분해 해서 (소인수 지수+1)의 곱을 구해 AB의 쌍의 개수를 구하고
N-x를 소인수분해 해서 (소인수 지수+1)의 곱을 구해 CD의 쌍의 개수를 구한다
그러면 두 개수의 곱이 (A,B,C,D)의 개수가 된다
def prime_factorization(n):
answer = 1
p = 2
count = 0
while p*p <= n:
while n % p == 0:
n = n // p
count += 1
p += 1
answer *= (count+1)
count = 0
if n > 1:
answer *= 2
return answer
n = int(input())
count1 = 0
count2 = 0
count = 0
for x in range(1,n):
y = n-x
count1 = prime_factorization(x)
count2 = prime_factorization(y)
count += (count1*count2)
count1 = 0
count2 = 0
print(count)
이러면 O(2N∗√N)인가..?
아무튼 이러면 시간안에 통과한다
5. editorial solution1
AB+CD = N에서 AB = X로 고정시키면, CD = N-X로 자동으로 결정된다
마찬가지로 A가 결정되면 B가 자동으로 결정되고 C가 결정되면 D가 자동으로 결정된다
그러므로 가장 첫번째 제시한 솔루션으로 O(N3)으로 X,A,C를 찾으면 답을 구할수는 있다
그런데 두번째 제시한 솔루션으로 AB = X인 (A,B)를 구하고 CD = N-X인 (C,D)를 구한 다음에 경우의 수 곱의 법칙으로 O(N2)에 구할 수 있음을 보였다
여기서 더 나아가서, A <= B이면 AB = X를 만족하는 A의 최댓값은 √X이므로 1부터 X의 제곱근 까지 순회해서,
AB를 나눠보고 나누어 떨어진다면 count + 1을 해준다.
이 경우, A < B인 경우만 셌으므로 count + 1을 더 해주어서 A > B인 경우도 해준다.
A = B인 경우는 오직 1가지만 존재하므로 count + 1을 추가적으로 하지 않는다
이러면 O(N√N)에 문제를 해결할 수 있다
n = int(input())
count1 = 0
count2 = 0
count = 0
for x in range(1,n):
y = n-x
for a in range(1,int(x**(1/2))+1):
if x % a == 0:
count1 += 1
if x != a*a:
count1 += 1
for c in range(1,int(y**(1/2))+1):
if y % c == 0:
count2 += 1
if y != c*c:
count2 += 1
count += (count1*count2)
count1 = 0
count2 = 0
print(count)
6. official solution2
AB = X를 만족하는 (A,B)의 개수는 결국 X의 약수의 개수이다.
x를 약수로 포함하는 어떤 정수들은 x, 2x, 3x, ... 로 x의 배수이다.
그러므로 길이 N인 counting 배열에서 x = 1, 2, 3, ..., N에 대해 N이하의 x의 모든 배수에 +1을 해주면 된다.
그러니까 N이하의 x,2x,3x,... 들은 (A,B) = (1,x), (2,x), (3,x), ...가 되는 것이다.
그리고 이들의 곱 x,2x,3x,..는 N이하이므로, AB+CD = N의 조건에 만족한다
(정답 개수 셀때는 N-1까지만 사용)
모든 경우를 순회하면 해당 배열의 index는 index의 약수의 개수가 된다.
이 때, CD = N-X이므로 counting[X] * counting[N-X]의 합이 정답
이 풀이가 놀라운 점은 AB = X를 만족시키는 (A,B)를 구하기 위해 X를 고정시켰는데
X를 고정시키지 않고 A,B를 각각 순회해서 (A,B)를 구한다는 점이다
n = int(input())
ab_list = [0]*(n+1)
for x in range(1,n):
for i in range(1,n//x+1):
ab_list[i*x] += 1
answer = 0
for i in range(1,n):
answer += (ab_list[i]*ab_list[n-i])
print(answer)
7. 최적화
바로 위 풀이에서 최적화할려면, AB = X에서 A <= B를 가정하고, 이럴 때 A의 최댓값은 √X
A를 1부터 √X까지 순회하여 a라고 한다면, A < B이므로, B는 a부터 X까지 순회한다.
그리고 ab가 N보다 커지면 counting 배열에 표시하지 말고 a == b이면 1만 증가시키고 a != b이면 2를 증가시키고
n = int(input())
ab_list = [0]*(n+1)
for a in range(1,int(n**(1/2))+1):
for b in range(a,n):
if a*b > n:
break
if a == b:
ab_list[a*b] += 1
else:
ab_list[a*b] += 2
count = 0
for i in range(1,n):
count += (ab_list[i] * ab_list[n-i])
print(count)
'경쟁 프로그래밍 > Atcoder' 카테고리의 다른 글
ABC 304 복기 - E good graph - union find 활용 (0) | 2023.06.04 |
---|---|
ABC 301 복기.. C - AtCoder Cards (문자열 그리디 알고리즘) (0) | 2023.05.14 |
그래프 연결요소 - union find로 찾아야하는 연결요소 문제 1 - (0) | 2023.03.14 |
ABC 293 복기 E - Geometric Progression - 행렬곱 배우기 - (0) | 2023.03.12 |
ABC 293 복기 - D Tying Rope - 그래프 연결요소, cycle 판단 - (0) | 2023.03.12 |