백준 4913번, 페르마의 크리스마스 정리 풀이
2020. 12. 26. 17:16ㆍProblem Solving/백준
문제
풀이
구간에 해당하는 소수를 빠르게 구하기 위해서,
구간 $[1, 100,000,000]$에 해당하는 모든 소수를 에라토스테네스의 체를 사용하여 구해줍니다.
해당 구간에 소수를 순서대로 넣으면, 정렬된 상태이기 때문에 이분 탐색을 사용할 수 있습니다.
문제 입력에서 주어지는 $[L, U]$에서 $upper(U) - lower(L) $한 수가 소수의 개수가 되겠네요.
비슷하게 제곱수의 합으로 나타낼 수 있는 수도 위처럼 구할 수 있습니다.
에라토스테네스의 체로 소수($p$)를 구할 때, $(p-1)mod4 = 0$을 만족하는 경우만 따로 관리해주면서, 위처럼 이분 탐색을 사용하여 풀 수 있습니다.
다만, $1^1 + 1^1 = 2$가 되는 "짝수인 소수 2"를 따로 고려해야 합니다.
소스코드
#include <bits/stdc++.h>
#define all(v) v.begin(), v.end()
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair <ll, ll> pll;
typedef vector<int> vi;
typedef vector <ll> vl;
const ll LIM = 1000000;
vl vis(LIM + 1), prime, euler = {2};
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
for (ll i = 2; i <= LIM; i++) {
if (vis[i]) continue;
prime.push_back(i);
if ((i - 1) % 4LL == 0) euler.push_back(i); //(p-1)%4==0이 되는 경우만 따로 관리
for (ll j = i; j <= LIM; j += i) vis[j] = 1;
}
while (1) {
ll l, u; cin >> l >> u;
if (l == -1 && u == -1) break;
int cnt = upper_bound(all(prime), u) - lower_bound(all(prime), l);
int ans = upper_bound(all(euler), u) - lower_bound(all(euler), l);
//이분 탐색을 사용해 구간 내에 존재하는 수들의 개수를 한번에 구할 수 있음
cout << l << " " << u << " " << cnt << " " << ans << "\n";
}
}
'Problem Solving > 백준' 카테고리의 다른 글
백준 1939번, 중량제한 풀이 (0) | 2021.01.07 |
---|---|
백준 2170번, 선 긋기 풀이 (0) | 2020.12.30 |
백준 14621번, 나만 안되는 연애 풀이 (0) | 2020.12.25 |
백준 15918번, 랭퍼든 수열쟁이야!! 풀이 (0) | 2020.12.22 |
백준 1644번, 소수의 연속합 풀이 (2) | 2020.12.21 |