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);
}
}