HDU5667Sequence (矩阵构造+费马小定理+矩阵快速幂)

Holion August will eat every thing he has found. 

        Now there are many foods,but he does not want to eat all of them at once,so he find a sequence. 

fn=⎧⎩⎨⎪⎪1,ab,abfcn−1fn−2,n=1n=2otherwisefn={1,n=1ab,n=2abfn−1cfn−2,otherwise 

        He gives you 5 numbers n,a,b,c,p,and he will eat fnfn foods.But there are only p foods,so you should tell him fnfn mod p.

Input

        The first line has a number,T,means testcase. 

        Each testcase has 5 numbers,including n,a,b,c,p in a line. 

    1≤T≤10,1≤n≤1018,1≤a,b,c≤109    1≤T≤10,1≤n≤1018,1≤a,b,c≤109,pp is a prime number,and p≤109+7p≤109+7.

Output

        Output one number for each case,which is fnfn mod p.

Sample Input

1
5 3 3 3 233

Sample Output

190

import java.util.Arrays;
import java.util.Scanner;

public class Main {
	static int T;
	static long n,a,b,c,p;
	static H_ mac=new H_();
	static H_ I=new H_();
	
	static long nummulti(long a,long b){//快速幂,求a^b
		long ans=1;
		while(b>0){
			if((b&1)==1) ans=a*ans%p;
			a=a*a%p;
			b>>=1;
		}
		return ans;
	}
	
	static long multi(H_ a,long n){//矩阵快速幂
		H_ ans=new H_();
		ans=I;
		while(n>0){
			if((n&1)==1) ans=multimod(a,ans);
			a=multimod(a,a);
			n>>=1;
		}
		return (ans.map[0][0]*b%(p-1)+ans.map[0][2]*b%(p-1))%(p-1);//这是初始矩阵p(2)=1,p(1)=0,还有个常数。即1 0 1,这是求取的p(n),再乘上b%(p-1)
	}
	
	static H_ multimod(H_ a, H_ b) {//矩阵乘法模运算
		H_ res=new H_();
		for(int i=0;i<3;i++){
			for(int j=0;j<3;j++){
				for(int k=0;k<3;k++){
					res.map[i][j]=(res.map[i][j]+a.map[i][k]*b.map[k][j]%(p-1))%(p-1);
				}
			}
		}
		return res;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);//注意数据的类型采用long型,矩阵快速幂的问题一般都是long
		T=sc.nextInt();
		while(T>0){
			n=sc.nextLong();
			a=sc.nextLong();
			b=sc.nextLong();
			c=sc.nextLong();
			p=sc.nextLong();
			I.map[0][0]=1;//初始化单位矩阵
			I.map[1][1]=1;//
			I.map[2][2]=1;
			
			mac.map[0][0]=c; mac.map[0][1]=1;mac.map[0][2]=1;//初始化连乘矩阵
			mac.map[1][0]=1; mac.map[1][1]=0;mac.map[1][2]=0;
			mac.map[2][0]=0;mac.map[2][1]=0;mac.map[2][2]=1;
			
			H_ res=new H_();
			if(n==1){
				System.out.println(1);
			}else if(a%p==0){//注意a%p==0,直接输出
				System.out.println("0");
			}else if(n==2){
				System.out.println(nummulti(a,b));注意不建议用pow误差太大
			}else{					
					System.out.println(nummulti(a,multi(mac,n-2)));	//代入快速幂		
			}			
			T--;
		}
	}

}
class H_{
	long map[][]=new long[3][3];
	public H_(){
		for(int i=0;i<3;i++)
			Arrays.fill(map[i],0);
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值