a[i] 앞으로 돌린 후 n번째 위치까지 올리는데 걸리는 횟수를 d[n]이라 하자. ( d[0] = 1 )


a1 a2 a3 a4 a5 가 있을 때 a6가 a4,a5 사이에 있어야 한다면 ( d[4] )


a6을 먼저 맨 앞으로 올린 후 a1을 올리고, a2를 다시 a1,a6 사이로 넣어야 한다. ( a1 -> d[0] )


a2를 a1,a6 사이로 올린 다음에는 a3를 맨 위로 올리고 다시 a3을 a2,a6 사이로 넣어야 한다. ( a2 -> d[1] )


그런식으로 계산해보면


a1 -> d[0]

a2 -> d[1] = a2->d[0] + a1->d[0]

a3 -> d[2] = a3->d[0] + a1->d[0] + a2->d[1]

a4 -> d[3] = a4->d[0] + a1->d[0] + a2->d[1] + a3->d[2]


d[4] = a6->d[0] + a1->d[0] + a2->d[1] + a3->d[2] + a4->d[3]


가 되고


이 된다.


이걸로 끝이 아니라 같은 원소가 여러개 있을 때를 생각해봐야 한다.


결론부터 말하자면 같은게 k개 있는 원소가 있으면 (k+1)/2^k 를 곱해주면 된다.


같은게 k개 있는 원소가 m개라면 ((k+1)/2^k)^m 을 곱해주면 된다.


#include <stdio.h>
#include <algorithm>
#include <math.h>
using namespace std;
 
typedef long long ll;
 
ll p[51];
 
int main() {
    int t;
    p[0= 1;
    for (int i = 1; i < 51++i) p[i] = p[i - 1* 2;
    scanf("%d"&t);
    while (t--) {
        int n, a[51], k;
        ll ans = 0;
        scanf("%d"&n);
        for (int i = 0; i < n; ++i) {
            scanf("%d"&a[i]);
            int j = 0, cnt[50= { 0, }, c[1001= { 0, };
            if (i&&a[i] >= a[i - 1]) continue;
            for (; j < i && a[i] > a[j]; ++j) {
                cnt[c[a[j]]]--;
                cnt[++c[a[j]]]++;
            }
            if (j == i) 
                continue;
            ll temp = p[j];
            for (k = 2; k < i + 1++k) {
                temp /= pow(p[k], (ll)cnt[k]);
                temp *= pow(ll(k + 1), (ll)cnt[k]);
            }
            ans += temp;
            sort(a, a + i + 1);
        }
        printf("%lld\n", ans);
    }
    return 0;
}
cs


'BOJ' 카테고리의 다른 글

14457 Cow Tipping  (0) 2018.11.10
1909 냄새 싫어  (0) 2018.11.07
16235 나무 재테크  (0) 2018.10.22
16236 아기 상어  (0) 2018.10.21
15684 사다리 조작  (0) 2018.08.29

+ Recent posts