코딩테스트준비

백준 2193. 이친수(DP)

haeullee 2023. 7. 10. 14:52

https://www.acmicpc.net/problem/2193

 

2193번: 이친수

0과 1로만 이루어진 수를 이진수라 한다. 이러한 이진수 중 특별한 성질을 갖는 것들이 있는데, 이들을 이친수(pinary number)라 한다. 이친수는 다음의 성질을 만족한다. 이친수는 0으로 시작하지 않

www.acmicpc.net

나는 문제 풀 때, 생각없이 직관적으로 푸는 습관이 있다. 구현문제처럼...

이 문제에 1<=n <=90이라는 조건이 없었으면, 나는 n이 가지는 이진수를 다 구하고, 앞자리 0인 이진수, 1연속인 이진수를 빼줬을 거같다. 다행히 문제에 조건이 있어서 이 방법을 시도하지 않았다. 

 

n=1, 2, 3일 때를 생각해보면 규칙을 발견할 수 있다. 

n = 2일 때의 이친수는 100 101이다. 

n = 3일 때의 이친수는 1000 1001 1010이다. 

n이 3일 때 나올 수 있는 이친수는 n이 2일 때 나올 수 있는 이친수의 맨 뒷자리가 0인 경우 2개, 맨 뒷자리가 1인 경우 1개 이다. 

따라서 점화식 d[i][0] = d[i-1][0] + d[i-1][1] (i 자리수의 이진수에서 맨뒷자리가 0인 경우), d[i][1] = d[i-1][0] (i 자리수의 이진수에서 맨뒷자리가 1인 경우)이다. 또한, i 번째 이친수의 개수는 d[i][0] + d[i][1]이다.

 

따라서 코드를 다음과 같이 작성한다. 

#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <limits.h>
#include <algorithm>
using namespace std;

int n;
int arr[92];
long long d[92][2]; //i자리 이진수이고 끝자리가 j일때 이친수 개수/ 이진수 개수를 저장하므로 long long
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);

    cin >> n;

    d[1][0]=0;
    d[1][1]=1;
    d[2][0]=1;
    d[2][1]=0;

    for(int i = 3; i <=n; i++)
    {
        d[i][0] = d[i-1][0] + d[i-1][1];
        d[i][1] = d[i-1][0];
    }

    cout << d[n][0] + d[n][1];

    

}