어떻게 풀까?
이전에 나왔던 타일링을 세는 문제와 매우 유사한 문제입니다.
이번에는 비대칭만을 세야하는 문제인데 어떻게 해결하면 좋을까요?
하나의 모형이 있다고 합시다. 그렇다면, 이 모형은 다음 2가지 중에 하나일 것입니다.
1. 대칭.
2. 비대칭.
생각보다 간단하지만, 이 문제의 해결 방법은 여기서부터 시작됩니다.
생각보다 대칭을 세는 것이 매우 쉽기 때문에, 비대칭의 개수는
전체의 개수 - 대칭의 개수 를 구하면 됩니다!!
그렇다면 대칭의 개수를 구하는 방법을 알아봅시다!!!
대칭인 경우는 크게 3가지 경우로 나눌 수 있습니다.
맨 위의 경우는 N이 홀수일 경우입니다. 이 경우에는 가운데에 무조건 세로 막대가 하나 있어야 합니다.
아래 2가지 경우에는 N이 짝수일 경우입니다.
파란색을 끼워 넣으면, 이제 나머지 회색 사각형의 부분이 똑같아야 대칭이 되는 것입니다.
그렇다면, 회색 부분에 만들 수 있는 비대칭 타일의 개수는 몇개일까요?
너비가 N이라고 했을 때 비대칭 타일의 수를 비대칭(N)이라고 한다면,
N이 홀수일 경우에는 비대칭((N-1)/2)개이고,
N이 짝수일 경우에는 비대칭(N/2 - 1) + 비대칭(N/2)개 일 것입니다.
이제 이를 통해 코드를 작성해 봅시다!
코드
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 | #pragma once #include<cstdio> int fibo[101] = { 1, 1 }; int sync[101] = {1, 1}; const int INF = 1000000007; int main() { int t; for (int i = 2; i <= 100; i++) { fibo[i] = (fibo[i - 1] + fibo[i - 2]) % INF; sync[i] = i & 1 ? fibo[(i - 1) / 2] : (fibo[i/2] + fibo[i/2 - 1]) % INF; } scanf("%d\n", &t); while (t--) { int n; scanf("%d\n", &n); printf("%d\n", (INF + fibo[n] - sync[n])%INF); } return 0; } | cs |
여담
결과를 출력할 때 INF를 더했다가 출력하는 것에 주목합시다!
이는 fibo와 sync에는 나머지값이 들어있기 때문입니다.
따라서, 오버플로우 때문에 fibo[n]값이 sync[n]값보다 작을 수도 있습니다.
따라서, fibo[n] - sync[n] 값이 음수로 나올수도 있습니다!
하지만 계산 방식을 저렇게 해 두면, 이제 0보다 작은 값이 나오는 것을 방지할 수 있습니다.
'공부 > 알고리즘 문제풀이' 카테고리의 다른 글
[알고스팟] 두니발 박사의 탈옥 (0) | 2018.06.17 |
---|---|
[알고스팟] 폴리오미노 (0) | 2018.06.17 |
[알고스팟] 삼각형 위의 최대 경로 개수 세기 (0) | 2018.06.16 |
[알고스팟] 타일링 방법의 수 세기 (0) | 2018.06.16 |
[알고스팟] Quantization (2) | 2018.06.15 |