java蓝桥杯练习 斐波那契

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));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值