SSL 1531 斐波拉契数列IV
Description–
求数列 f [ n ] = f [ n − 2 ] + f [ n − 1 ] + n + 1 f[n]=f[n-2]+f[n-1]+n+1 f[n]=f[n−2]+f[n−1]+n+1 的第 N N N 项,其中 f [ 1 ] = 1 , f [ 2 ] = 1 f[1]=1,f[2]=1 f[1]=1,f[2]=1
Input–
n n n
Output–
第 n n n 项结果 % 9973 \% 9973 %9973
Sample Input–
10000
Sample Output–
4399
说明–
1 < n < 2 31 − 1 1 < n < 2^{31} - 1 1<n<231−1
解题思路–
构造一个
1
×
4
1×4
1×4 的矩阵
【
f
[
n
−
2
]
,
f
[
n
−
1
]
,
n
,
1
】
【f[n-2],f[n-1],n,1】
【f[n−2],f[n−1],n,1】
因为
【
f
[
n
−
1
]
,
f
[
n
]
,
n
+
1
,
1
】
=
【
f
[
n
−
1
]
,
f
[
n
−
1
]
+
f
[
n
−
2
]
+
n
+
1
,
n
+
1
,
1
】
【f[n-1],f[n],n+1,1】= 【f[n-1],f[n-1]+f[n-2]+n+1,n+1,1】
【f[n−1],f[n],n+1,1】=【f[n−1],f[n−1]+f[n−2]+n+1,n+1,1】
所以 若构造一个矩阵
A
A
A 使
【
f
[
n
−
1
]
,
f
[
n
]
,
n
,
1
】
∗
A
=
【
f
[
n
]
,
f
[
n
+
1
]
,
n
+
1
,
1
】
【f[n-1],f[n],n,1】* A = 【f[n],f[n+1],n+1,1】
【f[n−1],f[n],n,1】∗A=【f[n],f[n+1],n+1,1】
则 易推
A
A
A 为
0 | 1 | 0 | 0 |
---|---|---|---|
1 | 1 | 0 | 0 |
0 | 1 | 1 | 0 |
0 | 1 | 1 | 1 |
代码–
#include <iostream>
#include <cstdio>
#define ll long long
using namespace std;
const ll M = 9973;
ll n;
struct ooo
{
ll aa, bb;
ll cc[5][5];
}a, b;
void hll()
{
a.aa = 4, a.bb = 4;
a.cc[1][1] = 0, a.cc[1][2] = 1, a.cc[1][3] = 0, a.cc[1][4] = 0;
a.cc[2][1] = 1, a.cc[2][2] = 1, a.cc[2][3] = 0, a.cc[2][4] = 0;
a.cc[3][1] = 0, a.cc[3][2] = 1, a.cc[3][3] = 1, a.cc[3][4] = 0;
a.cc[4][1] = 0, a.cc[4][2] = 1, a.cc[4][3] = 1, a.cc[4][4] = 1;
}
ooo operator *(ooo x, ooo y)
{
ooo c;
c.aa = x.aa, c.bb = y.bb;
for (ll i = 1; i <= c.aa; ++i)
for (ll j = 1; j <= c.bb; ++j)
c.cc[i][j] = 0;
for (ll k = 1; k <= x.bb; ++k)
for (ll i = 1; i <= c.aa; ++i)
for (ll j = 1; j <= c.bb; ++j)
c.cc[i][j] = (c.cc[i][j] + x.cc[i][k] * y.cc[k][j] % M) % M;
return c;
}
void ksm(ll x)
{
if (x == 1)
{
b = a;
return ;
}
ksm(x >> 1);
b = b * b;
if (x & 1) b = b * a;
}
int main()
{
hll();
scanf("%lld", &n);
if (n == 1) printf("1");
else
{
ksm(n - 1);
a.aa = 1;
a.cc[1][1] = a.cc[1][2] = a.cc[1][4] = 1, a.cc[1][3] = 3;
a = a * b;
printf("%lld", a.cc[1][1]);
}
return 0;
}