※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 13728번 문제인 행렬식과 GCD이다.
문제는 아래 링크를 확인하자.

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

 

13728번: 행렬식과 GCD

다음과 같은 원소를 갖는 크기가 N×N인 행렬이 있다. M(i, i) = 1 M(i, i+1) = 1 M(i, i-1) = -1 다른 값은 모두 0 예를 들어, 크기 N = 4인 경우 M은 다음과 같다. 1 1 0 0 -1 1 1 0 0 -1 1 1 0 0 -1 1 D(k)를 크기가 k×k인

www.acmicpc.net

 

먼저 주어진 형태의 n행 n열(n>2) tridiagonal matrix의 determinant Dn를 구하는 점화식을 유도해보자. 이 점화식은 먼저 우하단 원소를 기준으로 행방향으로 여인수 전개(Cofactor Expansion)을 하고, 그 다음으로 n1행 n1열 행렬꼴이 아닌 다른 행렬을 우하단 원소를 기준으로 열방향으로 여인수 전개하는 것으로 구할 수 있다. 구체적으로, 다음과 같은 점화식을 얻는다:

Dn=Dn1+Dn2

한편 D1=1D2=2임은 어렵지 않게 계산할 수 있다. 따라서 Dn=Fn+1이 성립한다. 여기서 Fn은 n번째 피보나치 수이다.

한편, gcd(Fi,Fj)=Fgcd(i,j)임은 well-known 지식이다. 이를 활용해 n+1번째까지의 피보나치 수(를 1000000007로 나눴을 때의 나머지)를 미리 구해두고 각 최대공약수번째 수를 하나하나 직접 더해 문제를 해결하자.

아래는 제출한 소스코드이다.

#include <iostream>
using namespace std;

int gcd(int x, int y) {
	if (y) return gcd(y, x % y);
	return x;
}

int F[100002];
int N, ans;

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	F[1] = 1;
	for (int i = 2; i < 100002; i++) {
		F[i] = F[i - 1] + F[i - 2];
		if (F[i] > 1000000006) F[i] -= 1000000007;
	}
	cin >> N; N++;
	for (int i = 2; i <= N; i++) {
		int g = gcd(i, N);
		ans += F[g];
		if (ans > 1000000006) ans -= 1000000007;
	}

	cout << ans;
}
728x90

+ Recent posts