• # 矩阵快速幂 计算Fibonacci数列(2020牛客1.J)


    J. u's的影响力

    题目:

    ​ 输入(n,x,y,a,b) 。输出 (x^{f(n-2)}*y^{f(n-1)}*a^{[f(n)-1]*b}) .其他f(i)表示Fibonacci数值

    题解:

    • 通过观察前几项得到上面的公式。利用矩阵快速幂可以计算很大的Fibonacci数,然后用快速幂求结果。
    • 快速幂中,如果x是模数的倍数,那么对于x=0,y=0的情况,qpow(0,0) = 1,但是应该输出0,这一点要特判一下。
    • 根据费马小定理,若 (p) 是正数,则对任意整数 (a) ,有 (a^{p} equiv a (mod p)) 。两边同时除 (a) 得, (a^{p-1} equiv 1 (mod p)) . 所以可以通过对幂取模来实现降幂。

    推荐博客:矩阵构造方法

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int MA=1e5+5;
    const ll mod=1e9+7;
    const ll P=1e9+6;
    
    struct mat{
    	ll m[3][3];
    	mat(){memset(m,0,sizeof(m));}
    };
    
    mat mul(mat x,mat y){	//矩阵乘法
    	mat res;
    	for(int i=0;i<3;++i)
    		for(int j=0;j<3;++j)
    			for(int k=0;k<3;++k)
    				res.m[i][j]=(res.m[i][j]+x.m[i][k]*y.m[k][j])%P;
    	return res;
    }
    
    mat power(mat A, ll n){	//矩阵快速幂
    	mat c=A,res;
    	for(int i=0;i<3;++i) res.m[i][i]=1;
    	while(n){
    		if(n&1) res=mul(res,c);
    		c=mul(c,c);
    		n>>=1;
    	}
    	return res;
    }
    
    ll qpow(ll x,ll y){	//快速幂
    	if(x%mod==0) return 0;
    	ll res=1;
    	while(y){
    		if(y&1) res=(res*x)%mod;
    		x=(x*x)%mod;
    		y>>=1;
    	}
    	return res;
    }
    
    
    ll n,x,y,a,b;
    
    int main()
    {
    	scanf("%lld%lld%lld%lld%lld",&n,&x,&y,&a,&b);
    	x%=mod, y%=mod, a%=mod , b%=P;
    	if(n == 1) printf("%lld
    ",x);
    	else if(n == 2) printf("%lld
    ",y);
    	else{
    		mat A,B,C;			//辅助矩阵
    		ll f1,f2,f3;		//辅助变量,存三个Fibonacci值
    		A.m[0][0] = 1, A.m[0][1] = 1, A.m[1][0] = 1;
    		B.m[0][0] = 0, B.m[1][0] = 1;
    		
    		
    		C=mul(power(A,n-2) , B);	//计算F(n-2)
    		f1=C.m[0][0] ;
    		
    		C=mul(power(A,n-1) , B);	//计算F(n-1)
    		f2=C.m[0][0] ;
    		
    		C=mul(power(A,n) , B);		//计算F(n);
    		f3=b*(C.m[0][0] -1 +P ) %P;
    
    		printf("%lld
    ",qpow(x,f1)%mod *qpow(y,f2)%mod * qpow(a,f3)%mod);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    通过构造函数检查生成对象个数
    动手动脑二
    产生随机数的几种方法
    素数输出
    递归实现回文串
    java的方法重载
    统计单词频率
    四则运算和随机验证码
    微信小程序--家庭记账本开发--04
    微信小程序--家庭记账本开发--03
  • 原文地址:https://www.cnblogs.com/A-sc/p/12275039.html
Copyright © 2020-2023  润新知