矩阵快速幂、快速乘还有鸡贼。
历届试题 斐波那契
时间限制:1.0s 内存限制:256.0MB
问题描述
斐波那契数列大家都非常熟悉。它的定义是:
f(x) = 1 .... (x=1,2)
f(x) = f(x-1) + f(x-2) .... (x>2)
对于给定的整数 n 和 m,我们希望求出:
f(1) + f(2) + ... + f(n) 的值。但这个值可能非常大,所以我们把它对 f(m) 取模。
公式如下
但这个数字依然很大,所以需要再对p 求模。
输入格式
输入为一行用空格分开的整数 n m p (0 < n, m,p < 10^18)
输出格式
输出为1个整数,表示答案
样例输入
2 3 5
样例输出
0
样例输入
15 11 29
样例输出
25
大佬的文章:点击打开链接
本菜鸡不会写这么复杂的,有空再来补上,,,
当m太大了longlong存不下了那么取模意义就不大了,m小的时候就直接套公式算吧。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n, m, p;
const ll N = 2, M = 2, P = 2;
struct Matrix{ll m[N][N];};
Matrix A={1,1,1,0};
Matrix I={1,0,0,1};
ll mul(ll a, ll b, ll MOD){
a = (a % MOD + MOD) % MOD;
b = (b % MOD + MOD) % MOD;
ll ans = 0;
if(a < b)
swap(a, b);
while(b > 0){
if(b & 1)
ans = (ans + a) % MOD;
a = (a + a) % MOD;
b >>= 1;
}
return ans;
}
Matrix multi(Matrix &a,Matrix &b, ll MOD)
{
Matrix ans;
for(int i=0;i<N;i++)//i, j控制行列
for(int j=0;j<M;j++)
{
ans.m[i][j]=0;
for(int k=0; k<P; k++){
ans.m[i][j] += mul(a.m[i][k], b.m[k][j], MOD);
ans.m[i][j] %= MOD;
}
}
return ans;
}
Matrix power(Matrix &a, ll k, ll MOD)
{
Matrix ans=I,z=a;
while(k > 0)
{
if(k&1){
ans=multi(ans,z, MOD);
}
k>>=1;
z=multi(z,z, MOD);
}
return ans;
}
ll solve(ll n, ll MOD)
{
Matrix ans=power(A,n-1, MOD);
return ans.m[0][0];
}
int main()
{
//freopen("input5.txt", "r", stdin);
scanf("%lld%lld%lld", &n, &m, &p);
if(m > 100){
ll ans = (solve(n + 2, p) - 1);
printf("%lld", (ans % p + p) % p);
}else{
ll fm = solve(m, 1e18);
ll ans = (solve(n + 2, 1e18) - 1) % fm;
printf("%lld", ans % p);
}
return 0;
}