您的位置:首页 > 其它

HDU 4549 M斐波那契数列(矩阵快速幂+费马小定理)

2017-07-18 19:47 621 查看


M斐波那契数列

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)

Total Submission(s): 3476    Accepted Submission(s): 1080


Problem Description

M斐波那契数列F
是一种整数数列,它的定义如下:

F[0] = a

F[1] = b

F
= F[n-1] * F[n-2] ( n > 1 )

现在给出a, b, n,你能求出F
的值吗?

 

Input

输入包含多组测试数据;

每组数据占一行,包含3个整数a, b, n( 0 <= a, b, n <= 10^9 )

 

Output

对每组测试数据请输出一个整数F
,由于F
可能很大,你只需输出F
对1000000007取模后的值即可,每组数据输出一行。

 

Sample Input

0 1 0
6 10 2

 

Sample Output

0
60

 

Source

2013金山西山居创意游戏程序挑战赛——初赛(2) 

 

中文题意。

POINT://其实还没学过矩阵到底怎么算,只知道2乘2的。

学习矩阵快速幂,可以用来求斐波那契数列。毕竟n非常大,递归肯定超时。

自己理解了一下,写了一个很丑的矩阵快速幂,只能求斐波那契数列。

费马小定理2:

我们可以利用费马小定理来简化幂模运算:由于a^(p-1)≡a^0≡1(mod p),所以a^x(mod p)有循环节,长度为p-1,所以a^x≡a^(x%(p-1))(mod p)

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <stack>
#include <algorithm>
#include <math.h>
using namespace std;
#define ll long long
const ll p =1e9+7;
const ll m=p-1;
ll a,b,n;
struct node
{
ll x11,x12,x21,x22;
};
node chen(node a,node b)
{
node ans;
(ans.x11=a.x11*b.x11+a.x12*b.x21)%=m;
(ans.x12=a.x11*b.x12+a.x12*b.x22)%=m;
(ans.x21=a.x21*b.x11+a.x22*b.x21)%=m;
(ans.x22=a.x21*b.x12+a.x22*b.x22)%=m;
return ans;
}
node jqkm(node now,ll mi)
{
if(mi<=0) return now;
node ans;
ans.x11=1,ans.x12=0,ans.x21=0,ans.x22=1;
while(mi)
{
if(mi&1)
{
ans=chen(ans,now);
}
mi=mi>>1;
now=chen(now,now);
}
return ans;
}
ll qkm(ll now, ll mi)
{
ll ans=1;
while(mi)
{
if(mi&1)
(ans*=now)%=p;
mi=mi>>1;
(now=now*now)%=p;
}
return ans;
}
ll baoli(ll x)
{
if(x==0) return a;
if(x==1) return b;
return baoli(x-1)*baoli(x-2)%p;
}
int main()
{
while(~scanf("%lld %lld %lld",&a,&b,&n))
{
ll f1=1,f2=2;
ll na,nb;
if(n<4)
{
printf("%lld\n",baoli(n));
}
else
{
node ans;
node now;
now.x11=1,now.x12=1,now.x21=1,now.x22=0;
ans=jqkm(now,n-3);
nb=ans.x11*f2+ans.x12*f1;
na=ans.x21*f2+ans.x22*f1;
printf("%lld\n",qkm(a,na)*qkm(b,nb)%p);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: