NYOJ 1000 又见斐波那契数列

来源:互联网 发布:时间简史 知乎 编辑:程序博客网 时间:2024/05/18 07:41

又见斐波那契数列
时间限制:1000 ms | 内存限制:65535 KB
难度:4
描述
斐波那契数列大家应该很熟悉了吧。下面给大家引入一种新的斐波那契数列:M斐波那契数列。 M斐波那契数列F[n]是一种整数数列,它的定义如下:

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

现在给出a, b, n,聪明的你能求出F[n]的值吗?
输入
输入包含多组测试数据;
每组数据占一行,包含3个整数a, b, n( 0 <= a, b, n <= 10^9 )
输出
对每组测试数据请输出一个整数F[n],由于F[n]可能很大,你只需输出F[n]对1000000007取模后的值即可,每组数据输出一行。
样例输入
0 1 0
6 10 2
样例输出
0
60

题解

F(0)=a,F(1)=b
F(n)=F(n−1)F(n−2)
⇒F(n)=F(n−2)2F(n−3)
⇒F(n)=F(n−3)3F(n−4)2
⇒F(n)=F(n−4)5F(n−5)3

⇒F(n)=F(1)f(n)F(0)f(n−1)
⇒F(n)=bf(n)af(n−1)
f(n)正是斐波那契数列。
矩阵快速幂可以求出f(n),f(n−1)的值。
然后快速幂计算bf(n),af(n−1), 答案就是两者乘积。
需要注意一点,取模是对F(n)取模,不是f(n),那么问题来了,f(n)会是一个很大的数,如果不模一下根本存不下,怎么办呢?
这里的模 p=1000000007,是个素数,由欧拉定理,
a^x≡a^(x%(p-1))(mod p)
所以f(n)可以对 p−1取模。
斐波那契数列就用矩阵快速幂去求:

这里写图片描述

最后再快速幂取模 GG

#include<cstring>#include<cstdio>#include<iostream>#include<cmath>#include<algorithm>#include<queue>#include<vector>#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;#define mod 1000000007#define PI acos(-1.0)typedef long long LL;typedef vector<LL> vec;typedef vector<vec> mat;// A*Bmat mul(mat& A, mat& B){    mat C(A.size(), vec(B[0].size()));    for(int i = 0; i < (int)A.size(); ++i)        for(int j = 0; j < (int)B[0].size(); ++j)            for(int k = 0; k < (int)B.size(); ++k)                C[i][j] = (C[i][j] + A[i][k] * B[k][j]) % (mod - 1);    return C;}// A^nmat pow_mat(mat A, LL n){    mat B(A.size(), vec(A.size()));    for(int i = 0; i < (int)A.size(); ++i) B[i][i] = 1;    while(n)    {        if(n & 1) B = mul(B, A);        A = mul(A, A);        n >>= 1;    }    return B;}LL quickpowmod(LL x,LL y,LL mo){      LL ret = 1;      while(y){         if(y&1)             ret = ret*x%mo;         x = x*x%mod;         y >>= 1;     }     return ret; }LL a,b,n;LL ans(LL a,LL b,LL n){    mat A(2,vec(2));    A[0][0]=1;    A[0][1]=1;    A[1][0]=1;    A[1][1]=0;    A=pow_mat(A,n);    LL x=A[1][0],y=A[1][1];    return (quickpowmod(b,x,mod)*quickpowmod(a,y,mod))%mod;}int main(){    while(cin>>a>>b>>n){        if(n==0)printf("%lld\n",a);        else if(n==1)printf("%lld\n",b);        else printf("%lld\n",ans(a,b,n));    }    return 0;}
0 0
原创粉丝点击