最近遇到费马小定理的一道应用题,思考了几个小时,理清了思路,终于证明了费马小定理求指数余以及矩阵幂求斐波那契结论;
先入为主(偷懒=_=),上题;
不一样的斐波那契数列(二)
Description
自从荟荟上了奥术课之后,她就觉得自己十分强大,但是万恶的数学老师说我们现在来讨论一下斐波那契数列。荟荟说,我知道。老师说,你知道很好,那么我们今天我们变形一下。
已知
F(0)=a
F(1)=b
F(n)=F(n-1)*F(n-2) (n>=2)
求F(n)
答案mod 1000000007 (1e9+7)
Input
多组数据输入,每组数据第一行输入三个整数a,b,n。
0<=a,b,n<=1e16
Output
对于每组数据输出F(n) mod 1000000007 (1e9+7)
#include<iostream>
#include<stdio.h>
// a ,b , ab ,a^1b^2 ,a^2b^3
//可以发现 数列F(N)的指数存在斐波那契的变化趋势,
//那么直接根据对应关系求出f(N)的 指数,最后用快速幂即可;
// 其中 矩阵求求斐波那契以及费马小定理的求余较难,但仔细想想就可以理解;
// 1.斐波那契数列 :1,1,2,3,5,8……
// 可以由矩阵求的;
// 构造矩阵A 1 0 系数矩阵B 1 1
// 0 1 1 0
//C(0)=A*B^0 = 1 0 C(1) = A*B^1= 1 1 C(2)=A*B^2= 2 1 ……
// 0 1 1 0 1 1
// 恰好 有c(N-1).x[1][0]是 F(N)的a的指数,同时C(N-1).x[0][0]是F(N)的b的指数;
//归纳说明:由此 可根据矩阵幂来求得斐波那契数;
// 2 . 费马小定理 的应用;
// 有公式: a^(p-1)(MOD p)= 1 (p为质数); 结论:(a^(M%(p-1)) )(mod p)=a^m(mod p);
// 证明如下: m=(p-1)*k+l;
// a^m(mod p)=( a^(l)*a^(k*(p-1)) )(mod p)
//= (a^(l)(mod p)*a^(k*(p-1))(mod p) ) (mod p)
//= a^(l)(mod p)
//= a^(M%(p-1)(mod p);
// 证毕;
// 也就是说 反正对指数就可以对其MOD(p-1);
// 神奇吧!
//3 还有个小问题:底数可不可以取余呢? 可以!
// 但是要取余P,而不是p-1;
// 道理和乘法求余公式一样的 :(a*b)(mod p)= (a mod p)*(b mod p )(mod p) ;
using namespace std;
typedef long long ll;
const int MOD = 1000000007;
const int MOD2 = 1000000006;
struct matrix{
ll x[2][2];
matrix()
{
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
x[i][j]=0;
}
};
typedef matrix mat;
mat mul(mat a, mat b){
mat tmp;
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
//费马小定理对指数的应用;
tmp.x[i][j] = (tmp.x[i][j] + (ll)a.x[i][k] * b.x[k][j] % MOD2) % MOD2;
return tmp;
}
mat quickmul(mat a,ll n)
{
mat ans;
for(int i=0;i<2;i++)
ans.x[i][i] = 1;
while(n>0)
{
if(n&1)
ans = mul(ans,a); //矩阵顺序???
n >>= 1;
a = mul(a,a);
}
return ans;
}
ll quickmi(ll a, ll p)
{
if(p==0)
return 1;
ll ans=1;
a = a % MOD;
p = p % MOD;
while(p>0)
{
if(p&1)
ans = (ans*a)%MOD;
a = (a*a)%MOD;
p >>= 1;
}
return ans;
}
void print(mat a)
{
for(int i=0;i<2;i++)
{
for(int j=0;j<2;j++)
cout<<a.x[i][j]<<' ';
cout<<endl;
}
}
int main(){
ll a,b,n,ans;
while(~scanf("%lld%lld%lld", &a,&b,&n))
{
if(n>0)
{
a %= MOD;
b %= MOD;
mat f1, fa;
f1.x[0][0]=1;f1.x[1][0]=1;f1.x[0][1]=1;
fa = quickmul(f1,n-1);
// print(fa);
ans = ( quickmi(a, fa.x[1][0] ) * quickmi(b,fa.x[0][0]) )% MOD;
// printf("%lld %lld \n",fa.x[1][0],fa.x[0][0]);
// printf("%lld %lld\n",( quickmi(a, fa.x[1][0] % (MOD-1) ) % MOD ), ( quickmi(b,fa.x[0][0]%(MOD-1)) % MOD ) );
printf("%lld\n", ans);
}
else
{
if(n==0)
printf("%d\n", a);
else if(n==1)
printf("%d\n", b);
}
}
}