java蓝桥杯练习 斐波那契
资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
斐波那契数列大家都非常熟悉。它的定义是:
f(x) = 1 … (x=1,2)
f(x) = f(x-1) + f(x-2) … (x>2)
对于给定的整数 n 和 m,我们希望求出:
f(1) + f(2) + … + f(n) 的值。但这个值可能非常大,所以我们把它对 f(m) 取模。
公式如下
但这个数字依然很大,所以需要再对 p 求模。
输入格式
输入为一行用空格分开的整数 n m p (0 < n, m, p < 10^18)
输出格式
输出为1个整数,表示答案
样例输入
2 3 5
样例输出
0
样例输入
15 11 29
样例输出
25
//java code
import java.math.BigInteger;
import java.util.*;
public class Main {
static BigInteger cal_fm[][]={{BigInteger.ONE,BigInteger.ONE},{BigInteger.ONE,BigInteger.ZERO}};
static BigInteger cal_sum[][]={{new BigInteger("2"),new BigInteger("0"),new BigInteger("-1")},
{new BigInteger("1"),new BigInteger("0"),new BigInteger("0")},
{new BigInteger("0"),new BigInteger("1"),new BigInteger("0")}};
static BigInteger MOD[][]={{BigInteger.ONE},{BigInteger.ONE}};
static BigInteger SUM[][]={{new BigInteger("4")},{new BigInteger("2")},{BigInteger.ONE}};
private static BigInteger[][] mult(BigInteger a[][],BigInteger b[][],BigInteger p,boolean flag){
int len=a.length;
int b_max=b[0].length;
int a_max=a[0].length;
if(a_max!=b.length) return null;
BigInteger ans[][]=new BigInteger[len][b_max];
for (int i = 0; i < len; i++) {
for (int j = 0; j < b_max; j++) {
BigInteger sum=BigInteger.ZERO;
for (int k = 0; k < a_max; k++) {
if(flag){
sum=(sum.mod(p)).add(a[i][k].multiply(b[k][j]).mod(p)).mod(p);
}else
sum=(sum.add(a[i][k].multiply(b[k][j])));
}
if(flag)
ans[i][j]=sum.mod(p);
else
ans[i][j]=sum;
}
}
return ans;
}
public static String fib(long n,long m,long p){
BigInteger mod=BigInteger.ZERO;
BigInteger sum=BigInteger.ZERO;
if(m>n+2){
if(n==1)
sum=BigInteger.ONE;
else{
n=n-1;
while (n!=0){
if((n&1)==1)
SUM=mult(cal_sum,SUM,new BigInteger(String.valueOf(p)),true);
n=n>>1;
cal_sum=mult(cal_sum,cal_sum,new BigInteger(String.valueOf(p)),true);
}
sum=SUM[2][0];
}
return sum.mod(new BigInteger(String.valueOf(p))).toString();
}
else {
if(m==1||m==2){
mod=BigInteger.ONE;
}
else {
m=m-1;
while (m!=0){
if((m&1)==1)
MOD=mult(cal_fm,MOD,new BigInteger(String.valueOf(p)),false);
m=m>>1;
cal_fm=mult(cal_fm,cal_fm,new BigInteger(String.valueOf(p)),false);
}
mod=MOD[1][0];
}
if(n==1)
sum=BigInteger.ONE;
else {
n=n-1;
while (n!=0){
if((n&1)==1)
SUM=mult(cal_sum,SUM,mod,true);
n=n>>1;
cal_sum=mult(cal_sum,cal_sum,mod,true);
}
sum=SUM[2][0];
}
return sum.mod(new BigInteger(String.valueOf(p))).toString();
}
}
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
long n=sc.nextLong();
long m=sc.nextLong();
long p=sc.nextLong();
System.out.println(fib(n,m,p));
}
}