※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 27435번 문제인 파도반 수열 2이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/27435
27435번: 파도반 수열 2
첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있고, N이 주어진다. (1 ≤ T ≤ 1,000, 1 ≤ N ≤ 1018)
www.acmicpc.net
파도반 수열(Padovan sequence)이란
실제로 주어진 그림에서 보조선을 적절히 그으면 위의 점화관계가 성립함을 알 수 있다. 예를 들어, 본문에 주어진 그림에서 "한 변의 길이가 4인 정삼각형와 5인 정삼각형의 맞닿은 변"을 한 변의 길이가 9인 정삼각형과 만날 때까지 연장한 보조선을 긋는다면 위의 점화식이 성립함을 간단히 관찰할 수 있다. (평행사변형을 잘 살펴보자.)
위의 점화식은 행렬을 이용해 아래와 같이 표현할 수 있다.
위와 같은 식과 적절한 초기값, 그리고 binary exponentiation을 이용해
파도반 수열에 대해 더 자세히 알고 싶다면 위키백과(링크)나 OEIS(링크) 등을 참고하자.
아래는 제출한 소스코드이다.
#define MOD 998244353
#include <iostream>
using namespace std;
typedef long long ll;
ll T, N[1000];
ll mat[3][3];
ll mtmp[3][3];
ll vec[1000][3];
ll vtmp[3];
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
mat[0][1] = mat[0][2] = mat[1][0] = mat[2][1] = 1;
cin >> T;
for (int t = 0; t < T; t++) cin >> N[t], vec[t][1] = 1;
for (int i = 0; i < 64; i++) {
for (int t = 0; t < T; t++) {
if (N[t] & 1) {
vtmp[0] = mat[0][0] * vec[t][0] + mat[0][1] * vec[t][1] + mat[0][2] * vec[t][2];
vtmp[1] = mat[1][0] * vec[t][0] + mat[1][1] * vec[t][1] + mat[1][2] * vec[t][2];
vtmp[2] = mat[2][0] * vec[t][0] + mat[2][1] * vec[t][1] + mat[2][2] * vec[t][2];
vec[t][0] = vtmp[0] % MOD, vec[t][1] = vtmp[1] % MOD, vec[t][2] = vtmp[2] % MOD;
}
N[t] >>= 1;
}
for (int r = 0; r < 3; r++) {
for (int c = 0; c < 3; c++) {
ll& cur = mtmp[r][c] = 0;
for (int k = 0; k < 3; k++) {
cur += mat[r][k] * mat[k][c];
}
}
}
for (int r = 0; r < 3; r++) {
for (int c = 0; c < 3; c++) {
mat[r][c] = mtmp[r][c] % MOD;
}
}
}
for (int t = 0; t < T; t++) cout << vec[t][0] << '\n';
}
'BOJ' 카테고리의 다른 글
[BOJ 1894 // C++] 4번째 점 (0) | 2023.02.10 |
---|---|
[BOJ 26099 // C++] 설탕 배달 2 (0) | 2023.02.10 |
[BOJ 9461 // C++] 파도반 수열 (0) | 2023.02.09 |
[BOJ 25905 // C++] 장인은 도구를 탓하지 않는다 (0) | 2023.02.09 |
[BOJ 2520 // C++] 팬케이크 사랑 (0) | 2023.02.09 |