寂寞的素数 斐波那契数列性质+矩阵连乘+欧拉定理 经典啊

题意:Fibonacci 数列是大家的老朋友了
Fib[1]=1, Fib[2]=1, Fib[3]=2……Fib[n]= Fib[n-1]+ Fib[n-2]
p是一个不甘寂寞的素数。某日它找到Fibonacci 数列,跳到Fibonacci 数列头上玩了起一个传说中的游戏。于是我们看到:
Fib[a]^p+ Fib[a+1]^p+ Fib[a+2]^p……….. + Fib[b]^p
好了,我们的问题来了,求上述表达式的值(即fab[i]的p次方之和,b>=i>=a),结果模p。

输入三个整数a、b、p,满足:
1000,000,000>a>0
1000,000,000>b>a
1000,000,000 > p

输出 一个整数。题目中要求表达式 模p 的结果

解析:由于欧拉定理:(a^α(p))%p=1; 其中α(p)p的欧拉函数值若α(p) p为质数那么α(p)=p-1

此题化简可得fib(i)^p%p=(a^(p-1))*a%p=a%p;

还有斐波那契数列的性质:f(0)+f(1)+……+f(n)=f(2+n)-1

又有斐波那契数列的公式f(0)+f+f+…+f(n)=f(n+2)-1。所以可以用矩阵连乘

#include<iostream>
using namespace std;
__int64 mod,sum,sta,end;
void mul(__int64 a[][2],__int64 b[][2])
{
     __int64 i,j,k,c[2][2];
     memset(c,0,sizeof(c));
     for ( i=0;i<2;i++ )
         for ( j=0;j<2;j++ )
             for ( k=0;k<2;k++ )
                 c[i][k]=(c[i][k]+a[i][j]*b[j][k]);
     for ( i=0;i<2;i++ )
         for ( j=0;j<2;j++ )
             a[i][j]=c[i][j]%mod;
}

__int64 solve(__int64 n)
{

        __int64 s[2][2],t[2][2],i,j;
        for ( i=0;i<2;i++ )
            for ( j=0;j<2;j++ )
                s[i][j]=(i==j);
        t[0][0]=t[0][1]=t[1][0]=1;
        t[1][1]=0;
        while ( n )
        {
              if ( n&1 )
                 mul(s,t);
             // if(n>=st-2 && n<=ed-2)
			//  sum+=(s[0][0]+s[1][0])%mod;
              mul(t,t);
             // if(n>=st-2 && n<=ed-2)
			 // sum+=(s[0][0]+s[1][0])%mod;
			  n>>=1;
              
        }
        return ((s[0][0]+s[1][0]));
}

int main()
{
    __int64 p;
    while ( scanf("%I64d%I64d%I64d",&sta,&end,&p)!=EOF)
    {
		mod=p;
		sum=0;
		__int64 aaa=solve(sta-1)-1;
	//	cout<<aaa<<endl;
		__int64 bbb=solve(end)-1;
	//	cout<<bbb<<endl;
		bbb=((bbb-aaa)%p+p)%p;//这里在mod完以后有可能bbb小于aaa所以加p在mod p处理  
		printf("%I64d\n",bbb);
		 
    }
    return 0;
}

你可能感兴趣的:(寂寞的素数 斐波那契数列性质+矩阵连乘+欧拉定理 经典啊)