https://www.acmicpc.net/problem/11390
11390번: 맛있는 과자
첫 번째 줄에 네 개의 자연수 a, b, N, K (1 ≤ a, b ≤ 100, 1 ≤ N ≤ 40, 1 ≤ K ≤ 2N)이 공백을 사이로 두고 주어진다.
www.acmicpc.net
DP문제를 돌다가 발견했는데 알고보니 그냥 수학문제. DP인 이유는 조합을 이용하기 때문이다.
STEP 0.
DP를 이용해 nCk (조합, Combination) 값들을 전부 배열 co[n][k]에 저장해준다.
STEP 1.

두 삼각형의 넓이비는 a^2 : b^2. 왜 그런지는 중학교 때 배운다.
a와 b를 입력받는데, a가 b보다 더 큰 값이라고 가정해보자. 어차피 입력받은 뒤 작은 게 a가 되도록 수정하면 되니 상관 X.
A=a^2;
B=b^2;
라고 둔다.
즉, 두 삼각형의 넓이비는 A:B이다.
한 번 더 나눈다면?
네 삼각형의 넓이비는 A^2 : AB : AB : B^2, 전체 넓이는 이항정리에 의해 (A+B)^2
또 나누면?
넓이가 A^p*B^(3-p)인 삼각형이 co[3][p]개 있을 것이다.
n번 나누면?
넓이가 A^p*B^(n-p)인 삼각형이 co[n][p]개 있을 것이다. (p가 작을수록 A^p*B^(n-p)가 크다.)
이건 비율만 생각하고 구한 것이기 때문에 전체 넓이를 (A+B)^n로 가정한 거다.
실제 삼각형의 넓이는 A^p*B^(n-p)/(A+B)^n * (a*b*1/2)인 것이다.
이제 p만 구하면 된다.
n=4인 경우를 예를 들어 보자.
조합은 1 4 6 4 1이다.
이건 X0>X1>X2>X3>.....이라고 할 때
넓이가 X0인 삼각형이 1개 있고
넓이가 X1인 삼각형은 4개 있고
넓이가 X2인 삼각형은 6개 있고 ...
넓이가 Xp인 삼각형인 nCp ( co[n][p] ) 개 있고...
이런 뜻이다.
참고로 Xp= A^p*B^(n-p)/(A+B)^n * (a*b*1/2)일 것이다.
그럼 예를들어 k=7이라면 넓이가 7번째로 큰 삼각형의 넓이는 X2일 것이다.
즉, k=7일 때 p=2
STEP 2.
이런 과정을 통해 p을 구했으니, 이제 log ( A^p*B^(n-p)/(A+B)^n * (a*b*1/2) )를 계산해주면 된다.
이 값은 로그의 성질에 의해
p * log(A) + (n - p) * log(B) - n * log(A + B) + log(a) + log(b) - log(2)
와 동일하다.
정확도를 높이기 위해 float가 아닌 double형을 사용한다.
그리고 소수점 아래 8번째 자리까지 정확도를 판단하니까 소수점 아래 13번째 자리 정도까지 출력하자.
다음은 C언어로 구현한 것이다.
|
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
|
#define MAX 45
typedef long long ll;
//STEP 0
ll co[MAX][MAX] = { 0 };//combination
void calcom() // MAX C MAX 까지 저장함
{
co[0][0] = 1;
for (int i = 1;i < MAX;i++)
{
co[i][0] = 1;
co[i][1] = i;
co[i][i - 1] = i;
co[i][i] = 1;
for (ll j = 1;j < i - 1;j++)
{
co[i][j] = co[i - 1][j - 1] + co[i - 1][j];
//co[i][j] %= DIV;
//DIV로 나눈 값을 배열에 저장
}
}
}
int main()
{
ll a, b, n, k;
scanf("%lld %lld %lld %lld", &a, &b, &n, &k);
calcom();
//STEP 1
if (a < b)
{
ll temp = b;
b = a;
a = temp;
}
ll A = a * a;
ll B = b * b;
ll h = 0;
ll p = 0;
for (;p < n + 1;p++)
{
h += co[n][p];
if (k <= h)
break;
}
//STEP 2
double x = p * log(A) + (n - p) * log(B) - n * log(A + B) + log(a) + log(b) - log(2);
printf("%.13f", x);
}
|
cs |
'problem solving' 카테고리의 다른 글
| 백준 16888: 루트 게임 (0) | 2023.02.24 |
|---|---|
| 백준 24678: 돌무더기 게임 1 (1) | 2023.02.24 |
| 백준 26156: 나락도 락이다 (3) | 2023.02.23 |
| 백준 19847: 여우 신탁 (0) | 2023.02.21 |
| 백준 1955: 수식 표현 (0) | 2023.02.20 |