파이썬에서 AtCoder Beginner Contest 177 E - Coprime
AtCoder Beginner Contest 177에 가입했습니다
D 완. E 문제로 막혔으므로 복습으로 정리합니다.
E - Coprime
프로덕션 중에 생각한 것
실질 "pairwise coprime를 어떻게 판정할까?"라는 문제.
어리석게 pairwise로 판정하면 당연히 시간이 걸리므로 소수 기준으로 생각할 수밖에 없다.
요컨대 「모든 $A_i$에 대해 소인수가 전혀 쓰지 않는다」라고 하는 것이므로, $A_i$를 소인수 분해해 나온 것을 카운트(p_cnt[$A_i$]에 +1) 해 가면 좋을 것 같다.
예: 12→2・3, 16→2, 35→5・7이므로, 2가 2회 이상 있어 pairwise가 아니다
p_cnt의 최대값이 1이면 pairwise coprime, 최대값이 N이면 not coprime, 그렇지 않으면 setwise coprime.
다만 1을 포함하는 경우가 코너 케이스이므로, 우선 전부 1이라면 pairwise coprime.
1, 1, 3, 6과 같이 1 이외가 coprime가 아닌 경우 setwise coprime,
1, 1, 3, 4 같은 경우라면 pairwise coprime.
따라서 각 $A_i$에 대해 생각할 때, 그것이 1이면 개수를 카운트하지 않게 한다.
# Nの素因数分解を辞書で返す
def prime_fact(n):
if n == 1:
return {1: 1}
root = int(math.sqrt(n))
prime_dict = {}
for i in range(2, root+1):
cnt = 0
while n % i == 0:
cnt += 1
n = n // i
if cnt:
prime_dict[i] = cnt
if n == 1:
break
if n != 1:
prime_dict[n] = 1
return prime_dict
def main():
N = int(input())
A = list(map(int, input().split()))
if max(A) == 1:
print("pairwise coprime")
exit()
p_cnt = defaultdict(int) # 素因数pが出てきた回数を記録
for a in A:
if a == 1: continue # 1の個数は数えてもしょうがないので無視
AP = prime_fact(a)
for apk in AP.keys():
p_cnt[apk] += 1
max_p = max(p_cnt.values())
if max_p == 1:
print("pairwise coprime")
elif max_p == N:
print("not coprime")
else:
print("setwise coprime")
1개(max_02.txt)만 TLE를 잡을 수 없다! ! 되어 타임업.
프로덕션 후에 생각한 것
C라면 어쨌든, Python(PyPy)에서는 $N$가 $10^6$도 있으면 힘들다.
여기서, 1,000,000 이하의 소수는 78,498 밖에 없는 것을 이용하는 것을 생각해 본다.
즉 $A_i$의 종류($len(set(A))$)가 대체로 8만 이상인 경우, 비둘기의 둥지 원리로부터 어딘가의 소인수에 반드시 커브가 발생해 pairwise coprime를 채우지 않게 된다! !
그래서 우선 적당히 gcd를 취해 not coprime의 케이스를 제외해 두고, 그다음에 8만 종류 이상 있는 케이스를 setwise coprime에 돌진하는 것으로, N을 실질 $10^6$에서 $10^5$정도까지 떨어뜨리는 것이 할 수 있다.
이 분기로 무사히 AC.
def main():
N = int(input())
A = list(map(int, input().split()))
if max(A) == 1:
print("pairwise coprime")
exit()
# 全Aiの最大公約数が1より大きければnot coprime
g = A[0]
for a in A:
g = math.gcd(g, a)
if g > 1:
print("not coprime")
exit()
# not coprimeでなく、Aが80000種類以上ならsetwise coprime
SA = set(A)
if len(SA) >= 80000:
print("setwise coprime")
exit()
# 上記でないケースのみ頑張る
p_cnt = defaultdict(int)
cnt = 0
for a in A:
if a == 1: continue
AP = prime_fact(a)
for apk in AP.keys():
p_cnt[apk] += 1
max_p = max(p_cnt.values())
if max_p == 1:
print("pairwise coprime")
else:
print("setwise coprime")
보다 강한 테스트 케이스에는 지는 생각이 들기 때문에 온순하게 해설의 고속화를 사용합시다.
Reference
이 문제에 관하여(파이썬에서 AtCoder Beginner Contest 177 E - Coprime), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/Mao-beta/items/f6a50f9586e4d976b474
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
프로덕션 중에 생각한 것
실질 "pairwise coprime를 어떻게 판정할까?"라는 문제.
어리석게 pairwise로 판정하면 당연히 시간이 걸리므로 소수 기준으로 생각할 수밖에 없다.
요컨대 「모든 $A_i$에 대해 소인수가 전혀 쓰지 않는다」라고 하는 것이므로, $A_i$를 소인수 분해해 나온 것을 카운트(p_cnt[$A_i$]에 +1) 해 가면 좋을 것 같다.
예: 12→2・3, 16→2, 35→5・7이므로, 2가 2회 이상 있어 pairwise가 아니다
p_cnt의 최대값이 1이면 pairwise coprime, 최대값이 N이면 not coprime, 그렇지 않으면 setwise coprime.
다만 1을 포함하는 경우가 코너 케이스이므로, 우선 전부 1이라면 pairwise coprime.
1, 1, 3, 6과 같이 1 이외가 coprime가 아닌 경우 setwise coprime,
1, 1, 3, 4 같은 경우라면 pairwise coprime.
따라서 각 $A_i$에 대해 생각할 때, 그것이 1이면 개수를 카운트하지 않게 한다.
# Nの素因数分解を辞書で返す
def prime_fact(n):
if n == 1:
return {1: 1}
root = int(math.sqrt(n))
prime_dict = {}
for i in range(2, root+1):
cnt = 0
while n % i == 0:
cnt += 1
n = n // i
if cnt:
prime_dict[i] = cnt
if n == 1:
break
if n != 1:
prime_dict[n] = 1
return prime_dict
def main():
N = int(input())
A = list(map(int, input().split()))
if max(A) == 1:
print("pairwise coprime")
exit()
p_cnt = defaultdict(int) # 素因数pが出てきた回数を記録
for a in A:
if a == 1: continue # 1の個数は数えてもしょうがないので無視
AP = prime_fact(a)
for apk in AP.keys():
p_cnt[apk] += 1
max_p = max(p_cnt.values())
if max_p == 1:
print("pairwise coprime")
elif max_p == N:
print("not coprime")
else:
print("setwise coprime")
1개(max_02.txt)만 TLE를 잡을 수 없다! ! 되어 타임업.
프로덕션 후에 생각한 것
C라면 어쨌든, Python(PyPy)에서는 $N$가 $10^6$도 있으면 힘들다.
여기서, 1,000,000 이하의 소수는 78,498 밖에 없는 것을 이용하는 것을 생각해 본다.
즉 $A_i$의 종류($len(set(A))$)가 대체로 8만 이상인 경우, 비둘기의 둥지 원리로부터 어딘가의 소인수에 반드시 커브가 발생해 pairwise coprime를 채우지 않게 된다! !
그래서 우선 적당히 gcd를 취해 not coprime의 케이스를 제외해 두고, 그다음에 8만 종류 이상 있는 케이스를 setwise coprime에 돌진하는 것으로, N을 실질 $10^6$에서 $10^5$정도까지 떨어뜨리는 것이 할 수 있다.
이 분기로 무사히 AC.
def main():
N = int(input())
A = list(map(int, input().split()))
if max(A) == 1:
print("pairwise coprime")
exit()
# 全Aiの最大公約数が1より大きければnot coprime
g = A[0]
for a in A:
g = math.gcd(g, a)
if g > 1:
print("not coprime")
exit()
# not coprimeでなく、Aが80000種類以上ならsetwise coprime
SA = set(A)
if len(SA) >= 80000:
print("setwise coprime")
exit()
# 上記でないケースのみ頑張る
p_cnt = defaultdict(int)
cnt = 0
for a in A:
if a == 1: continue
AP = prime_fact(a)
for apk in AP.keys():
p_cnt[apk] += 1
max_p = max(p_cnt.values())
if max_p == 1:
print("pairwise coprime")
else:
print("setwise coprime")
보다 강한 테스트 케이스에는 지는 생각이 들기 때문에 온순하게 해설의 고속화를 사용합시다.
Reference
이 문제에 관하여(파이썬에서 AtCoder Beginner Contest 177 E - Coprime), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/Mao-beta/items/f6a50f9586e4d976b474텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)