题目:
大家都知道 Fibonacci 数列吧,f1=1,f2=1,f3=2,f4=3,…,fn=fn−1+fn−2f1=1,f2=1,f3=2,f4=3,…,fn=fn−1+fn−2。
现在问题很简单,输入 nn 和 mm,求 fnfn 的前 nn 项和 SnmodmSnmodm。
输入格式
共一行,包含两个整数 nn 和 mm。
输出格式
输出前 nn 项和 SnmodmSnmodm 的值。
数据范围
1≤n≤20000000001≤n≤2000000000,
1≤m≤10000000101≤m≤1000000010
输入样例:
5 1000
输出样例:
12
思路整理:
矩阵公式推理:
Fn = [fn fn+1]
Fn+1 = [fn+1 fn+2] fn+2 = fn+1 + fn
= [fn fn+1] * [0 1]
[1 1]
X = {
{0, 1}
{1, 1} }
Fn = [fn fn+1]
Fn+1 = [fn fn+1]*X
Fn+1 = Fn * X
Fn = Fn-1 * X (n>=2)
...
F3 = F2 * X = F1 * X * X
F2 = F1 * X
-> Fn = F1 * X^(n-1)
F1 = [1 1]
Fn = [1 1] * X^(n-1)
---------------------求和分割线------------------------------------
Fn = [fn fn+1 sn]
Fn+1 = [fn+1 fn+2 sn+1]
= Fn * { [0 1 0]
[1 1 1]
[0 0 1] }
X = { [0 1 0]
[1 1 1]
[0 0 1] }
F2 = F1 * X = [1 1 2]*X
F3 = F2 * X = F1 * X * X
...
Fn = F1 * X^(n-1)
= [1 1 1] * { [0 1 0]
[1 1 1]
[0 0 1] } ^(n-1)
sn = Fn[2]
代码:
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const LL maxn = 2e9 + 7;
#define fori(i,n) for(int i = 0; i < n; i++)
LL n, m;
LL f1[3] = {1, 1, 1};
LL x[3][3] = {
{0, 1, 0},
{1, 1, 1},
{0, 0, 1}
};
LL res[3][3];
void matrixMul_2(LL a[][3], LL b[][3], LL c[][3])
{
LL ans[3][3];
fori(i, 3)
{
fori(j, 3)
{
ans[i][j] = 0;
fori(k, 3)
{
ans[i][j] = (ans[i][j] + a[i][k]*b[k][j]) % m;
}
}
}
memcpy(c, ans, sizeof(ans));
}
void matrixMul_1(LL a[], LL b[][3])
{
LL c[3];
fori(i, 3)
{
c[i] = 0;
fori(j, 3)
{
c[i] = (c[i] + a[j] * b[j][i]) % m;
}
}
memcpy(a, c, sizeof(c));
}
int main()
{
scanf("%lld%lld", &n, &m);
n--;
while(n)
{
if(n&1) matrixMul_1(f1, x);
n>>=1;
matrixMul_2(x, x, x);
}
printf("%lld", f1[2]);
return 0;
}