历届试题 斐波那契
时间限制: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
思路:S(n)=f(n+2)-1
原式=(f(n+2)-1)%f(m)%p 再利用矩阵快速幂求f()
Code:
#include<iostream>
#include<cstring>
using namespace std;
typedef long long LL;
LL llmul( LL a,LL b,LL mod ) {
a%=mod;a+=mod;a%=mod;
b%=mod;b+=mod;b%=mod;
if ( a<b ) swap( a,b );
LL ret=0;
while ( b ) {
if ( b&1 )ret=( ret+a )%mod;
a=( a<<1 )%mod;
b/=2;
}
return ret;
}
struct matrix {
LL x[3][3];
matrix() {memset( x,0,sizeof x );}
};
matrix mmul( matrix &A,matrix &B,LL mod ) {
matrix ret;
for ( int i=1; i<=2; i++ )
for ( int j=1; j<=2; j++ )
for ( int k=1; k<=2; k++ )
ret.x[i][j]=( ret.x[i][j]+llmul( A.x[i][k],B.x[k][j],mod ) )%mod;
return ret;
}
matrix E,A;
LL fib( LL n,LL mod ) {
matrix O=E,B=A;
while ( n ) {
if ( n&1 )O=mmul( O,B,mod );
B=mmul( B,B,mod );
n/=2;
}
return O.x[1][2];
}
LL solve( LL n,LL m,LL mod ) {
//f(n)%f(m)%mod
LL t=n/m;
//(f(m-1)^t*f(n%m))%f(m)%mod;
//f(i)^2%f(i-1)=(-1)^(i+1)
LL p=t/2,q=t%2;
//{f(m-1)^q*(-1)^(pm)*f(n%m)}%f(m)%mod
LL fuhao=p*m%2==0?1:-1;
if ( q==0 ) {
LL ans=fib( n%m,mod )*fuhao;
ans%=mod;
ans+=mod;
return ans%mod;
}
if ( n%m==0 )return 0;
//f(m-1)*f(n%m)*fuhao%f(m)%mod
//x%y%mod=(x-a*y)%mod
//a=[x/y]
LL x=(llmul(fib(n%m,mod),fib(m-1,mod),mod)*fuhao%mod+mod)%mod;
LL y=fib(m,mod);
LL a=fib(n%m-1,mod);
if(n%m%2==0) a--;
if(fuhao<0) a++;
a=(a%mod+mod)%mod;
return ((x-llmul(a,y,mod))%mod+mod)%mod;
}
int main ()
{
A.x[1][2]=A.x[2][1]=A.x[2][2]=1;
E.x[1][1]=E.x[2][2]=1;
LL n,m,mod;
while ( cin>>n>>m>>mod )
cout<<( solve( n+2,m,mod )-1+mod )%mod<<endl;
return 0;
}
code:
#include <iostream>
using namespace std;
typedef long long LL;
const int N = 2;
LL MOD;
struct Matrix{
LL m[N][N];
};
Matrix I = {
1, 0,
0, 1
};
Matrix A = {
1, 1,
1, 0
};
Matrix multi(Matrix A, Matrix B)
{
Matrix C;
for(int i = 0; i < N; i++)
for(int j = 0; j < N; j++)
{
C.m[i][j] = 0;
for(int k = 0; k < N; k++)
C.m[i][j] += A.m[i][k] * B.m[k][j];
C.m[i][j] %= MOD;
}
return C;
}
Matrix Power(Matrix A, LL n)
{
Matrix ans = I, P = A;
while(n) {
if(n & 1){
ans = multi(ans, P);
n--;
}
n >>= 1;
P = multi(P, P);
}
return ans;
}
//计算F(n) % MOD
LL getFun(LL n)
{
Matrix ans = Power(A, n);
return ans.m[1][0];
}
//计算F(m - 1) * F(n % m) mod F(m)
LL getRes(LL n, LL m)
{
LL k = n % m;
if(k & 1)
return getFun(m - k);
return ((getFun(m) - getFun(m - k)) % MOD + MOD) % MOD;
}
LL Solve(LL n, LL m)
{
LL t1 = n / m;
if(m & 1){
LL t2 = t1 >> 1;
if(t1 % 2 == 0 && t2 % 2 == 0)
return getFun(n % m);
if(t1 % 2 == 0 && t2 % 2 == 1)
return ((getFun(m) - getFun(n % m)) % MOD + MOD) % MOD;
if(t1 % 2 == 1 && t2 % 2 == 0)
return getRes(n, m);
if(t1 % 2 == 1 && t2 % 2 == 1)
return ((getFun(m) - getRes(n, m)) % MOD + MOD) % MOD;
}else{
if(t1 & 1) return getRes(n, m);
else return getFun(n % m);
}
}
LL getResponse(LL n, LL m)
{
LL res = Solve(n, m);
if(res == 0) //f(n)之和
return getFun(m) - 1;
return res - 1;
// return res;
}
int main()
{
ios::sync_with_stdio(false);
LL n, k;
while(cin>>n>>k>>MOD){
cout<<getResponse(n+2, k)<<endl;
}
return 0;
}