HDU4990Reading comprehension (矩阵快速幂构造)奇怪

Read the program below carefully then answer the question. 
#pragma comment(linker, "/STACK:1024000000,1024000000") 
#include <cstdio> 
#include<iostream> 
#include <cstring> 
#include <cmath> 
#include <algorithm> 
#include<vector> 

const int MAX=100000*2; 
const int INF=1e9; 

int main() 

  int n,m,ans,i; 
  while(scanf("%d%d",&n,&m)!=EOF) 
  { 
    ans=0; 
    for(i=1;i<=n;i++) 
    { 
      if(i&1)ans=(ans*2+1)%m; 
      else ans=ans*2%m; 
    } 
    printf("%d\n",ans); 
  } 
  return 0; 
}

Input

Multi test cases,each line will contain two integers n and m. Process to end of file. 
[Technical Specification] 
1<=n, m <= 1000000000

Output

For each case,output an integer,represents the output of above program.

Sample Input

1 10
3 100

Sample Output

1
5

先用题干函数输出m=100前几项的结果,得到1 2 5 10 21 42 85

找规律得到递推式f(n)=f(n-1)+2*f(n-2)+1;

构造矩阵

f(n)         1        2         1        f(n-1)

f(n-1) *    1        0         0     * f(n-2)

1             0        0         1          1

矩阵快速幂

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

public class Main {
	static long n,m,ans;
	static J_ I=new J_();
	static J_ mac=new J_();
	static int maxn=3;
	
	static J_ jz(J_ a,long n){//矩阵快速幂
		J_ ans=new J_();
		ans=I;//第一个矩阵
		while(n>0){
			if((n&1)==1) ans=jzmod(a,ans);
			n>>=1;
			a=jzmod(a,a);
		}
		return ans;
	}
	
	static J_ jzmod(J_ a,J_ b){//矩阵乘法
		J_ res=new J_();
		for(int i=0;i<maxn;i++){
			for(int j=0;j<maxn;j++){
				for(int k=0;k<maxn;k++){
					res.map[i][j]=(res.map[i][j]+a.map[i][k]*b.map[k][j]%m)%m;
				}
			}
		}
		return res;
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);
		while(sc.hasNext()){
			n=sc.nextLong();
			m=sc.nextLong();
									
			I.map[0][0]=2;//初始第二项f(2)
			I.map[1][0]=1;//初始第一项f(1)
			I.map[2][0]=1;
			
			mac.map[0][0]=1;mac.map[0][1]=2;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;
			if(n==1){
				System.out.println(1%m);//因为我们不确定m的大小,都要模
			}else if(n==2){
				System.out.println(2%m);//因为我们不确定m的大小,都要模
			}else{
				J_ res=new J_();
				res=jz(mac,n-2);
				System.out.println(res.map[0][0]);
			}						
		}
	}
}
class J_{
	long[][] map=new long[3][3];
	J_(){
		for(int i=0;i<3;i++)
			Arrays.fill(map[i],0);
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值