HDOJ M斐波那契数列 4549【矩阵快速幂+快速幂+费马小定理+欧拉函数】

M斐波那契数列

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

Total Submission(s): 2096    Accepted Submission(s): 596

Problem Description

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

F[0] = a

F[1] = b

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

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

Input

输入包含多组测试数据;

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

Output

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

Sample Input

0 1 0
6 10 2

Sample Output

0
60

Source

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

Recommend

liuyiding   |   We have carefully selected several similar problems for you:  5390 5389 5388 5387 5386

题目分析:

此题是求的相乘的斐波那契数,开始看成求相加斐波那契,以为是很裸的矩阵快速幂。。。

不过,此题虽然让求的是相乘的过程。但是当你写出几个数之后就会发现这些数的指数是成斐波那契数列的。

3  4  12  48.....  ==>  3^1*4^0   3^0*4^1   3^1*4^1    3^1*4^2.........

我们可以求出让求的第n项指数是多少。但是因为让求的数比较多,所以结果肯定会比较大,我们要想到对指数取余。我们想到费马小定理:

a ^ n = a ^ (n % euler ( M ) )*( mod M )

题目中说的是结果对M=1000000007取余,所以我们对指数取余的数应为euler(M)。因为M是素数,所以euler(M)=1000000006。

下面我们很容易就能找到相乘的矩阵,进行快速幂。不过注意题目的n,题目n代表的是n+1项。

开始的时候我找的相乘的矩阵是3*3的矩阵。。。。开始TLE了,以为是矩阵的原因,改成了2*2的。。。逗比了。。其实不是矩阵太大。。多了一维而已慢不了哪里。。主要是应该long long型的,写int就TLE。。。long long就过了。

AC代码。。3*3的相乘矩阵

#include <stdio.h>
#include <math.h>
#include <vector>
#include <queue>
#include <string>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>

using namespace std;

const int Modn = 1000000007;
const int MAXN = 3;
typedef long long LL;
LL res[MAXN][MAXN];

void Matmul(LL X[MAXN][MAXN],LL Y[MAXN][MAXN])
{
    int t[MAXN][MAXN]={0};
    for(int i=0;i<MAXN;i++){
        for(int k=0;k<MAXN;k++){
            if(X[i][k])
                for(int j=0;j<MAXN;j++)
                t[i][j]=(t[i][j]+X[i][k]*Y[k][j]%(Modn-1))%(Modn-1);
        }
    }
    for(int i=0;i<MAXN;i++)
        for(int j=0;j<MAXN;j++)
        X[i][j]=t[i][j];
}

void Matrix(LL X[MAXN][MAXN],LL n)
{
    for(int i=0;i<MAXN;i++){
        //res[i][i]=1;
        for(int j=0;j<MAXN;j++)
            res[i][j]=(i==j);
    }
    while(n){
        if(n&1) Matmul(res,X);
        Matmul(X,X);
        n>>=1;
    }
}

LL power(LL x,LL n)
{
    x%=Modn;
    LL res=1;
    while(n){
        if(n&1) res=res*x%Modn;
        x=x*x%Modn;
        n>>=1;
    }
    return res;
}

int main()
{

    LL a,b,n;
    while(scanf("%lld%lld%lld",&a,&b,&n)!=EOF){
        if(n<3){
            if(n==0)printf("%lld\n",a);
            else if(n==1) printf("%lld\n",b);
            else if(n==2) printf("%lld\n",a*b);
            continue;
        }
        LL num[MAXN][MAXN];
        LL f[3];
        memset(num,0,sizeof(num));
        num[0][0]=num[0][1]=1;
        num[1][2]=num[1][0]=1;
        Matrix(num,n-2);//(n+1)-3;
        f[2]=1;f[1]=0;f[0]=1;
        LL ans1=0;
        for(int j=0;j<3;j++)
            ans1=(ans1+f[j]*res[j][0]%(Modn-1))%(Modn-1);
        f[2]=0;f[1]=1;f[0]=1;
        LL ans2=0;
        for(int j=0;j<3;j++)
            ans2=(ans2+f[j]*res[j][0]%(Modn-1))%(Modn-1);
        LL cnt=power(a,ans1)*power(b,ans2)%Modn;
        printf("%lld\n",cnt);
    }
    return 0;
}

2*2的相乘矩阵

#include <stdio.h>
#include <math.h>
#include <vector>
#include <queue>
#include <string>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>

using namespace std;

const int Modn = 1000000007;
const int MAXN = 2;
typedef long long LL;
LL res[MAXN][MAXN];

void Matmul(LL X[MAXN][MAXN],LL Y[MAXN][MAXN])
{
    LL t[MAXN][MAXN]={0};
    for(int i=0;i<MAXN;i++){
        for(int k=0;k<MAXN;k++){
            if(X[i][k])
                for(int j=0;j<MAXN;j++)
                t[i][j]=(t[i][j]+X[i][k]*Y[k][j]%(Modn-1))%(Modn-1);
        }
    }
    for(int i=0;i<MAXN;i++)
        for(int j=0;j<MAXN;j++)
        X[i][j]=t[i][j];
}

void Matrix(LL X[MAXN][MAXN],LL n)
{
    for(int i=0;i<MAXN;i++){
        //res[i][i]=1;
        for(int j=0;j<MAXN;j++)
            res[i][j]=(i==j);
    }
    while(n){
        if(n&1) Matmul(res,X);
        Matmul(X,X);
        n>>=1;
    }
}

LL power(LL x,LL n)
{
    x%=Modn;
    LL ans=1;
    while(n){
        if(n&1) ans=ans*x%Modn;
        x=x*x%Modn;
        n>>=1;
    }
    return ans;
}

int main()
{

    LL a,b,n;
    while(scanf("%lld%lld%lld",&a,&b,&n)!=EOF){
        if(n<3){
            if(n==0)printf("%lld\n",a);
            else if(n==1) printf("%lld\n",b);
            else if(n==2) printf("%lld\n",a*b);
            continue;
        }
        LL num[MAXN][MAXN];
        LL f[3];
        num[0][0]=num[1][0]=num[0][1]=1;
        num[1][1]=0;
        Matrix(num,n-1);//(n+1)-3;
        f[1]=1;f[0]=0;
        LL ans1=0;
        for(int j=0;j<MAXN;j++)
            ans1=(ans1+f[j]*res[j][0]%(Modn-1))%(Modn-1);
        //printf("%d ",ans1);
        f[1]=0;f[0]=1;
        LL ans2=0;
        for(int j=0;j<MAXN;j++)
            ans2=(ans2+f[j]*res[j][0]%(Modn-1))%(Modn-1);
        //printf("%d \n",ans2);
        LL cnt=power(a,ans1)*power(b,ans2)%Modn;
        printf("%lld\n",cnt);
    }
    return 0;
}

M斐波那契数列

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

Total Submission(s): 2096    Accepted Submission(s): 596

Problem Description

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

F[0] = a

F[1] = b

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

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

Input

输入包含多组测试数据;

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

Output

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

Sample Input

0 1 0
6 10 2

Sample Output

0
60

Source

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

Recommend

liuyiding   |   We have carefully selected several similar problems for you:  5390 5389 5388 5387 5386

版权声明:本文为博主原创文章,转载请注明出处。

时间: 2024-10-13 15:37:04

HDOJ M斐波那契数列 4549【矩阵快速幂+快速幂+费马小定理+欧拉函数】的相关文章

hdu 4549 M斐波那契数列(矩阵快速幂,快速幂降幂)

http://acm.hdu.edu.cn/showproblem.php?pid=4549 f[0] = a^1*b^0%p,f[1] = a^0*b^1%p,f[2] = a^1*b^1%p.....f[n] = a^fib[n-1] * b^fib[n-2]%p. 这里p是质数,且a,p互素,那么我们求a^b%p,当b很大时要对b降幂. 因为a,p互素,那么由费马小定理知a^(p-1)%p = 1.令b = k*(p-1) + b',a^b%p = a^(k*(p-1)+b')%p = a

斐波那契数列的矩阵推导(看不懂的可以放弃矩阵了)

一.矩阵乘法 设矩阵A,B 满足 :A的列数==B的行数 矩阵乘法的运算规则: 将A矩阵的每一行乘以B矩阵的每一列 * == == 二.斐波那契数列的矩阵推导 首先我们想 Fib[i]=Fib[i-1]+Fib[i-2]; 所以斐波那契数列的第i项之与两个数也就是Fib[i-1]+Fib[i-2]有关 那么我们可以设第一个矩阵 M1= 因为我们需要利用矩阵推出斐波那契的第n项 所以我们设M1的下一项为M3 则M3=(也就是让M1的下标整体后移一位) 那么现在我们需要一个过渡矩阵M2来实现这个从M

【矩阵快速幂】HDU 4549 : M斐波那契数列(矩阵嵌套)

[题目链接]click here~~ [题目大意] M斐波那契数列F[n]是一种整数数列,它的定义如下: F[0] = a F[1] = b F[n] = F[n-1] * F[n-2] ( n > 1 ) 现在给出a, b, n,你能求出F[n]的值吗?对每组测试数据请输出一个整数F[n],由于F[n]可能很大,你只需输出F[n]对1000000007取模后的值即可,每组数据输出一行. [Source] :2013金山西山居创意游戏程序挑战赛――初赛(2) [解题思路] 这个题稍微有点难度,就

HDU 4549 M斐波那契数列(矩阵快速幂)

Problem Description M斐波那契数列F[n]是一种整数数列,它的定义如下: F[0] = a F[1] = b F[n] = F[n-1] * F[n-2] ( n > 1 ) 现在给出a, b, n,你能求出F[n]的值吗? Input 输入包含多组测试数据: 每组数据占一行,包含3个整数a, b, n( 0 <= a, b, n <= 10^9 ) Output 对每组测试数据请输出一个整数F[n],由于F[n]可能很大,你只需输出F[n]对1000000007取模

HDU 4549 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]的值吗? Input 输入包含多组测试数据: 每组数据占一行,包含3个整数a, b, n( 0 <= a, b, n <= 10^9 ) Output 对每组测试数据请输出一个整数F[n],由于F[n]可能很大,你只需输出F[n]对1000000007取模后的值即可,每组数据输出一行. Samp

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

M斐波那契数列 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 1672    Accepted Submission(s): 482 Problem Description M斐波那契数列F[n]是一种整数数列,它的定义如下: F[0] = aF[1] = bF[n] = F[n-1] * F[n-2] ( n > 1 ) 现在给出a,

快速求斐波那契数列(矩阵乘法+快速幂)

斐波那契数列 给你一个n:f(n)=f(n-1)+f(n-2) 请求出 f(f(n)),由于结果很大请 对答案 mod 10^9+7; 1<=n<=10^100; 用矩阵乘法+快速幂求斐波那契数列是经典应用: 矩阵公式 C i j=C i k *C k j; 根据递推式 构造2*2矩阵: 原始矩阵 1 0 0 1 矩阵 2 1 1 1 0 原始矩阵与矩阵 2相乘达到转化状态效果: 对矩阵二进行快速幂 乘法:达到快速转化矩阵的效果: 即使达到快速转化状态:那么大的数据范围也很难求解: 高精?这有

#斐波那契数列用矩阵快速幂求解f(n)#

通常情况下,斐波那契数列第n项可以通过递归求解或者直接求解但当n非常大的时候,求解f(n)将显得非常困难下面利用矩阵以及快速幂的方法在logn复杂度内求解 则可以运用快速幂来求解矩阵高次幂,复杂度降为logn 来自为知笔记(Wiz)

洛谷1349 广义斐波那契数列 【矩阵乘法】

洛谷1349 广义斐波那契数列 题目描述 广义的斐波那契数列是指形如an=p*an-1+q*an-2的数列.今给定数列的两系数p和q,以及数列的最前两项a1和a2,另给出两个整数n和m,试求数列的第n项an除以m的余数. 输入输出格式 输入格式: 输入包含一行6个整数.依次是p,q,a1,a2,n,m,其中在p,q,a1,a2整数范围内,n和m在长整数范围内. 输出格式: 输出包含一行一个整数,即an除以m的余数. 输入输出样例 输入样例#1: 1 1 1 1 10 7 输出样例#1: 6 说明