일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- trie
- html5
- ccw 알고리즘
- Prisma
- Express.js
- 게임 서버 아키텍처
- branch
- 그리디
- MySQL
- insomnia
- Keys
- string
- PROJECT
- MongoDB
- 이분 탐색
- HTTP
- 자바스크립트
- 트라이
- 그래프 탐색
- outer join(외부 조인)
- Github
- map
- router
- localstorage
- 백준 10775번
- pm2
- JavaScript
- ERD
- DP
- Next
Archives
- Today
- Total
dh_0e
[PS] 너 봄에는 캡사이신이 맛있단다 / C++ (백준 15824번) 본문


조합론이 기본이 되는 문제로 계산식 발상에 좀 애먹은 문제
결론적으로 메뉴들을 맵기 순으로 정렬하면, 메뉴마다 가장 높은 수치, 낮은 수치일 경우의 수가 정해져 있으므로 각각의 메뉴마다 경우의 수를 조합론으로 구해 계산해주면 된다.
풀이과정
한 메뉴가 포함되는 조합의 수는 총 2n−1−1가지이다.
하지만 스코빌 수치가 이용되는 경우만 따지면 되기 때문에 i번째 메뉴가 가장 높은 스코빌 수치일 때와 가장 낮을 때만 구해주면 된다. 식으로 나타내면 다음과 같다. (i가 0~n-1일 때)
가장 높은 스코빌 수치일 경우 >> 2i−1
가장 낮은 스코빌 수치일 경우 >> 2n−i−1−1
i번째 메뉴보다 높거나 낮은 스코빌을 선택할 때 모두 선택하지 않은 경우의 수가 있기 때문에 -1을 해줌
2n을 구할 때 n이 300,000까지 일 경우 O(n2)으로는 시간 초과가 나기 때문에 이를 다음 2 방법으로 처리해주면 된다.
- 거듭제곱을 활용한 분할정복 O(nlogn)
- dp로 전처리 O(n)
거듭제곱을 활용한 분할정복으로 2의 배수 계산 O(nlogn)
#define MOD 1000000007
#include<iostream>
#include<algorithm>
typedef long long ll;
using namespace std;
ll d[3000001];
ll power_n(ll val, int time) {
if (time == 1)return val;
if (time % 2 == 1)return (power_n(val * val % MOD, time / 2) * val) % MOD;
else return power_n(val * val % MOD, time / 2) % MOD;
}
int main()
{
int n;
ll dap = 0;
scanf("%d", &n);
for (int i = 0; i < n; i++)scanf("%lld", &d[i]);
sort(d, d + n);
for (int i = 0; i < n; i++) {
if (i != 0)dap += (d[i] * (power_n(2, i) - 1)) % MOD + MOD;
if (i != n - 1)dap -= (d[i] * (power_n(2, n - i - 1) - 1)) % MOD;
}
cout << dap % MOD << endl;
return 0;
}
dp로 2의 배수 30만까지 전처리 후 계산 O(n)
#define MOD 1000000007
#include<iostream>
#include<algorithm>
typedef long long ll;
using namespace std;
ll d[3000001];
ll be[300001];
void prepro(int n) {
ll temp = 1;
for (int i = 0; i <= n; i++) {
be[i] = temp;
temp *= 2;
temp %= MOD;
}
return;
}
int main()
{
int n;
ll dap = 0;
scanf("%d", &n);
for (int i = 0; i < n; i++)scanf("%lld", &d[i]);
sort(d, d + n);
prepro(n);
for (int i = 0; i < n; i++) {
if (i != 0)dap += (d[i] * (be[i] - 1)) % MOD + MOD;
if (i != n - 1)dap -= (d[i] * (be[n - i - 1] - 1)) % MOD;
}
cout << dap % MOD << endl;
return 0;
}
'알고리즘 > Baekjoon' 카테고리의 다른 글
[PS] 공항 / C++ (백준 10775번) (0) | 2025.04.11 |
---|---|
[PS] 뱀과 사다리 게임 / C++ (백준 16928번) (0) | 2025.04.09 |
[PS] 박성원 / C++ (백준 1086번) (0) | 2025.03.25 |
[PS] 두 배열의 합 / C++ (백준 2143번) (0) | 2025.03.20 |
[PS] GCD(n, k) = 1 / C++ (백준 11689번) (0) | 2025.03.14 |