[UVA][矩陣 D&C] 12470 - Tribonacci
Problem J. Tribonacci
13th Century
Everybody knows about Fibonacci, they guy who invented the famous sequence where the first two terms are 0 and 1 and from then on every term is the sum of the previous two.
What most people don’t know is that he had a somewhat mentally retarded brother named Tribonacci. In a desperate attempt to surpass his brother and achieve eternal glory, Tribonacci invented his own sequence: the first three terms are 0, 1, 2 and from then on every term is the sum of the previous three.
Sadly, regardless of enormous courage and dedication, Tribonacci was never able to compute more than the first 3 terms of his sequence. Even more sadly, one cold night he performed an extraordinary mental effort that dilated one of the blood vessels in his brain, causing severe hemorrhage and killing him instantly. This is clinically known as an aneurysm, but of course Tribonacci did not know this (it is suspected that even pronouncing the word aneurysm would have been an impossible task for him).
Write a program that changes history and finds the nth term in the Tribonacci sequence modulo 1,000,000,009.
Input
The input contains several test cases (at most 400).
Each test case contains a single integer n (1 ≤ n ≤ 1016), the desired term in the Tribonacci sequence.
The last line of the input contains a single 0 and should not be processed.
Output
For each test case, output the nth term in the Tribonacci sequence on a single line. This number might be huge, so output the number modulo 1,000,000,009.
Sample input and output
standard input
|
standard output
|
|
|
1
2 3 4 5 6 7 8 9 10 100 10000 10000000 100000000000 10000000000000000 0 |
0
1 2 3 6 11 20 37 68 125 616688122 335363379 272924536 48407255 163452242 |
作法 : 矩陣 D&C
[1 1 0]
[1 0 1]
[1 0 0]
[an an-1 an-2]
A = [an-1 an-2 an-3]
[an-2 an-3 an-4]
#include <stdio.h>
#define mod 1000000009
struct M {
long long v[3][3];
} I = {1,0,0,0,1,0,0,0,1},
o = {0,0,0,0,0,0,0,0,0},
A = {1,1,0,1,0,1,1,0,0};
void multiply(M &x, M &y) {
static int i, j, k;
static M t;
t = o;
for(i = 0; i < 3; i++) {
for(j = 0; j < 3; j++) {
for(k = 0; k < 3; k++) {
t.v[i][j] += x.v[i][k]*y.v[k][j];
t.v[i][j] %= mod;
}
}
}
x = t;
}
M solve(long long n) {
M x = I, y = A;
while(n > 0) {
if(n&1)
multiply(x, y);
n /= 2;
multiply(y, y);
}
return x;
}
int main() {
long long n;
while(scanf("%lld", &n) == 1 && n) {
if(n == 1)
puts("0");
else if(n == 2)
puts("1");
else if(n == 3)
puts("2");
else {
M res = solve(n-3);
printf("%lld\n", (res.v[1][0]+res.v[0][0]*2)%mod);
}
}
return 0;
}