반응형
문제 출처 :
https://www.acmicpc.net/problem/1644
알고리즘 분석 :
문제 해결에 필요한 사항
1. Prefix Sum :: http://www.crocus.co.kr/259
2. 투 포인터
http://www.crocus.co.kr/595 (1806번 부분합) 문제와 상당히 유사한 문제이다.
다른 점이라고는 소수를 배열에 넣어줘야 한다는 것이고 그 외에는 방식이 모두 같다.
투 포인터에 대해 이해를 하고, 그에 맞게 p1와 p2를 조작할 수 있다면 해결할 수 있는 문제이다.
자세한 내용은 주석을 통해 달아두었다.
소스 코드 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | #include <iostream> #include <cstdio> #include <memory.h> #include <math.h> #define MAX_N 4000001 using namespace std; unsigned char sieve[(MAX_N + 7) / 8]; int pSum[MAX_N]; // K가 소수인지 확인한다. inline bool isPrime(int k) { return sieve[k >> 3] & (1 << (k & 7)); } // k가 소수가 아니라고 표시한다. inline void setComposite(int k) { sieve[k >> 3] &= ~(1 << (k & 7)); } // 비트 마스크를 사용하는 에라토스테네스의 체의 구현 // 이 함수를 수행하고 난 뒤, isPrime()을 이용해 각 수가 소수인지 알 수 있다. void eratosthenes(int n) { memset(sieve, 255, sizeof(sieve)); setComposite(0); setComposite(1); int sqrtn = int(sqrt(n)); for (int i = 2; i <= sqrtn; ++i) // 이 수가 아직 지워지지 않았다면 if (isPrime(i)) // i의 배수 j들에 대해 isPrime[i] = false로 둔다. // i*i 미만의 배수는 이미 지워졌으므로 신경 쓰지 않는다. for (int j = i*i; j <= n; j += i) setComposite(j); } int main() { int n, p1 = 0, p2 = 1; int ans = 0; int cnt = 0; int size; scanf("%d", &n); eratosthenes(n); // 소수의 부분 합을 구한다. while (p1 <= n) { if (isPrime(p1)) { pSum[p2] = pSum[p2 - 1] + p1; p2++; } p1++; } size = p2 - 1; p1 = 1; p2 = 1; // p1이 오버 플로우 되는 경우 break while (!(p1 > size && p1 > p2)) { // p1~p2까지 합이 n과 같으면 if (pSum[p2] - pSum[p1 - 1] == n) { cnt++; // p1 == p2면 p2 증가 if (p1 == p2) p2++; // 그외는 p1 증가 else p1++; } // p1~p2까지 합이 n보다 작으면 else if (pSum[p2] - pSum[p1 - 1] < n) { // p2가 아직 끝점 도달하지 못했을 경우 p2 증가 if (p2 < size) p2++; // 그외 p1 증가 else p1++; } // p1~p2까지 합이 n보다 크면 else { // p1을 증가시켜보고 부분합을 검사한다. p1++; if (pSum[p2] - pSum[p1 - 1] == n) { cnt++; p1++; } } } cout << cnt; return 0; } // This source code Copyright belongs to Crocus // If you want to see more? click here >> | Crocus |
반응형
'Applied > 알고리즘 문제풀이' 카테고리의 다른 글
[3078번] 좋은 친구 (1) | 2017.02.16 |
---|---|
[2096번] 내려가기 (0) | 2017.02.14 |
[1806번] 부분합 (0) | 2017.02.13 |
[2581번] 소수 (0) | 2017.02.13 |
[11377번] 열혈강호 3 (4) | 2017.02.10 |