小X的暑假作业

问题描述
  小X的作业是老师给他布置的,题目很简单,求出第N个斐波那契数 mod P的值。小X怎么想也想也想不出来,只好求助于你了。
输入格式
  第一行为数据组数T。
  第二行开始,以下T行,每行为老师给小X布置的作业中的N和P。
输出格式
  包含T行,每行是一个作业的答案。
样例输入
3
7 3
1000000 89
987654321 30000
样例输出
0
55
19111
数据规模和约定
  对于50%的数据,T<=100,N<=10000。
  对于100%的数据,T<=10000,N<=1000000000,P<=30000。
  斐波那契数的第0个是1。

 

public class 小X的暑假作业 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
    Scanner sc=new Scanner(System.in);
    int T=sc.nextInt();
    while(T-->0){
         long n=sc.nextLong();
         int p=sc.nextInt();
          long q[][]={{0,1},{1,1}};//下标从0开始
          long a[][]={{1,1}};
          long res[][];
          long end[][];
          res=matrixpower(q,n-1,p); //res为q矩阵的n-1次方
          end=mutiply(a,res,p); //mutiply实现两个矩阵相乘
          System.out.println(end[0][0]%p);    
     }
    }

    private static long[][] matrixpower(long[][] q, long n,int p) { //实现矩阵q的n次
        long[][] res=new long[2][2];
        //把res矩阵初始化为单位矩阵
        for(int i=0;i<q.length;i++){
            res[i][i]=1;
        }
        //快速幂实现
        while(n>0){
            if((n&1)==1){
                res = mutiply(res, q,p);
            }
            q =mutiply(q, q,p);//乘方一直翻倍
            n>>=1;
        }
        return res;
    }

    private static long[][] mutiply(long[][] a, long[][] b,int p) {
        long[][] res=new long[a.length][b.length];
        for(int i=0;i<a.length;i++){
            for(int j=0;j<b.length;j++){
                long temp=0;
                for(int k=0;k<a[0].length;k++){
                    temp= ((temp+(a[i][k]*b[k][j])%p))%p; 
                }
                res[i][j]=temp;
            }
        }
        return res;
    }

}

 

posted @ 2021-03-20 22:11  nb小歪  阅读(51)  评论(0)    收藏  举报