※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 14860번 문제인 GCD 곱이다.
문제는 아래 링크를 확인하자.

https://www.acmicpc.net/problem/14860 

 

14860번: GCD 곱

N과 M 이 주어졌을 때, GCD(1, 1) × GCD(1, 2) × ... × GCD(1, M) × GCD(2, 1) × GCD(2, 2) × ... × GCD(2, M) × ... × GCD(N, 1) × GCD(N, 2) × ... × GCD(N, M)을 구하는 프로그램을 작성하시오.

www.acmicpc.net

모든 수의 쌍에 대하여 gcd를 구한다면 시간초과가 날 것이다.

대신, gcd를 구성하는 수를 소인수별로 구해서 그 개수를 한번에 binary exponentiation으로 곱해주면 빠르게 계산할 수 있다.

 

소수를 구할 때 i*i가 32비트 정수 범위를 넘어설 수 있음에 유의하자.

 

어디서 Clang의 단순 연산 반복문의 최적화 성능이 좋다는 말을 주워들어서 gcc와 clang 모두 제출해보았더니 이 문제에 대한 글쓴이의 코드는 clang이 더 빠르게 채점이 된다는 사실을 알 수 있었다.

 

아래는 제출한 소스코드이다.

#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;

vector<bool> sieve(15000001);
vector<ll> primes;

ll ans = 1;

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	int N, M; cin >> N >> M;
	int x = min(N, M);
	for (ll i = 2; i <= x; i++) {
		if (sieve[i]) continue;
		primes.push_back(i);
		for (ll j = i * i; j <= x; j += i) sieve[j] = 1;
	}
	for (auto p : primes) {
		ll pp = p;
		ll cnt = 0;
		while (pp <= x) {
			cnt += (N / pp) * (M / pp);
			pp *= p;
		}
		while (cnt > 0) {
			if (cnt & 1) {
				ans *= p;
				ans %= 1000000007;
			}
			cnt >>= 1;
			p *= p;
			p %= 1000000007;
		}
	}

	cout << ans;
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 16566 // C++] 카드 게임  (0) 2021.07.06
[BOJ 17409 // C++] 증가 수열의 개수  (0) 2021.07.05
[BOJ 3088 // C++] 화분 부수기  (0) 2021.07.03
[BOJ 13976 // C++] 타일 채우기 2  (0) 2021.07.02
[BOJ 5032 // C++] 탄산 음료  (0) 2021.07.01

+ Recent posts