题目1444:蓝桥杯2014年第五届真题斐波那契

简介: 题目1444:蓝桥杯2014年第五届真题斐波那契

这篇文章是帮一个叫做【废柴成长中】的孩子写的。

题目:

这里难点应该就是在【输入为一行用空格分开的整数n m p(0<n,m,p<10^18)】 ,这里一下子就把最大值干成long的最大范围了,很明显,long肯定也不行。

解析其实不是太麻烦,先分析,然后咱们在一点点的编写出来。

题目中给的【fib(n) = fib(n+2)-fib(n+1)】这个方法应该分数不高,不然就直接能做出来了。

我们还得对超大数据进行操作,我这里选用的是【BigInteger】,毕竟这是纯整数,求余计算结果也是纯整数或0,就是计算起来没有直接写符号计算的方便而已。

看人家给的公式:

大致先写成这样,反正看的明白就行(Σ(n)f(i))modf(m)

已知:fib(n) = fib(n+2)-fib(n+1)

推导:Σf(n) = f(n+2)-1

推算一下变量m:

如果 m>=n+2那么f(m)>Σf(n),结果是(f(n+2)-1)%p,

反之结果为(f(n+2)-1)%f(m)%p==f(n+2)%f(m)%p-1。

直接上代码,其实很多时候看debug是最快的调试方案:

package com.example.demo2022110201;
/**
 * @author
 */
import java.math.BigInteger;
import java.util.Scanner;
public class Demo1 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        // 三变量
        long n, m, p;
        n = sc.nextLong();
        m = sc.nextLong();
        p = sc.nextLong();
        BigInteger bigP = BigInteger.valueOf(p);
        if (m >= n + 2) {
            BigInteger ans = fib(n + 2, bigP);
            System.out.println(ans.mod(bigP).longValue() - 1);
        } else {
            BigInteger fib_m = fib(m);
            BigInteger ans = fib(n + 2, fib_m);
            System.out.println(ans.mod(fib_m).mod(bigP).longValue() - 1);
        }
        sc.close();
    }
    /**
     * 快速矩阵求fib
     *
     * @param m
     * @return
     */
    private static BigInteger fib(long m) {
        BigInteger[][] ans = mPow(m - 2);
        return ans[0][0].add(ans[1][0]);
    }
    private static BigInteger fib(long m, BigInteger mod) {
        BigInteger[][] ans = mPow(m - 2, mod);
        return ans[0][0].add(ans[1][0]);
    }
    /**
     * 矩阵快速幂
     *
     * @param n
     * @return
     */
    private static BigInteger[][] mPow(long n) {
        BigInteger[][] a =
                {{BigInteger.ONE, BigInteger.ONE}, {BigInteger.ONE, BigInteger.ZERO}};
        //基础矩阵
        BigInteger[][] ans =
                {{BigInteger.ONE, BigInteger.ZERO}, {BigInteger.ZERO, BigInteger.ONE}};
        while (n != 0) {
            if ((n & 1) == 1) {
                BigInteger t1 = ans[0][0];
                BigInteger t2 = ans[1][0];
                ans[0][0] = ans[0][0].multiply(a[0][0]).add(ans[0][1].multiply(a[1][0]));
                ans[0][1] = t1.multiply(a[0][1]).add(ans[0][1].multiply(a[1][1]));
                ans[1][0] = ans[1][0].multiply(a[0][0]).add(ans[1][1].multiply(a[1][0]));
                ans[1][1] = t2.multiply(a[0][1]).add(ans[1][1].multiply(a[1][1]));
            }
            BigInteger t1 = a[0][0];
            BigInteger t2 = a[1][0];
            BigInteger t3 = a[0][1];
            a[0][0] = a[0][0].multiply(a[0][0]).add(a[0][1].multiply(a[1][0]));
            a[0][1] = t1.multiply(a[0][1]).add(a[0][1].multiply(a[1][1]));
            a[1][0] = a[1][0].multiply(t1).add(a[1][1].multiply(a[1][0]));
            a[1][1] = t2.multiply(t3).add(a[1][1].multiply(a[1][1]));
            n >>= 1;
        }
        return ans;
    }
    private static BigInteger[][] mPow(long n, BigInteger mod) {
        BigInteger[][] a =
                {{BigInteger.ONE, BigInteger.ONE}, {BigInteger.ONE, BigInteger.ZERO}};
        //基础矩阵
        BigInteger[][] ans =
                {{BigInteger.ONE, BigInteger.ZERO}, {BigInteger.ZERO, BigInteger.ONE}};
        while (n != 0) {
            if ((n & 1) == 1) {
                //结果乘当前平方
                BigInteger t1 = ans[0][0];
                BigInteger t2 = ans[1][0];
                ans[0][0] = ans[0][0].multiply(a[0][0]).add(ans[0][1].multiply(a[1][0])).mod(mod);
                ans[0][1] = t1.multiply(a[0][1]).add(ans[0][1].multiply(a[1][1])).mod(mod);
                ans[1][0] = ans[1][0].multiply(a[0][0]).add(ans[1][1].multiply(a[1][0])).mod(mod);
                ans[1][1] = t2.multiply(a[0][1]).add(ans[1][1].multiply(a[1][1])).mod(mod);
            }
            //算平方
            BigInteger t1 = a[0][0];
            BigInteger t2 = a[1][0];
            BigInteger t3 = a[0][1];
            //如果是其它语言就换成自己语言的大数处理即可。
            a[0][0] = a[0][0].multiply(a[0][0]).add(a[0][1].multiply(a[1][0])).mod(mod);
            a[0][1] = t1.multiply(a[0][1]).add(a[0][1].multiply(a[1][1])).mod(mod);
            a[1][0] = a[1][0].multiply(t1).add(a[1][1].multiply(a[1][0])).mod(mod);
            a[1][1] = t2.multiply(t3).add(a[1][1].multiply(a[1][1])).mod(mod);
            n >>= 1;
        }
        return ans;
    }
}

测试数据,我这没有平台,故而直接用测试用例的【15 11 29】,结果【25】正确

相关文章
|
9天前
|
人工智能 算法 搜索推荐
蓝桥杯宝藏排序题目算法(冒泡、选择、插入)
以下是内容的摘要: 本文介绍了三种排序算法:冒泡排序、选择排序和插入排序。冒泡排序通过不断交换相邻的逆序元素逐步排序,最坏情况下需要 O(n^2) 次比较。选择排序在每轮中找到剩余部分的最小元素并放到已排序序列的末尾,同样具有 O(n^2) 时间复杂度。插入排序则是将每个元素插入到已排序序列的正确位置,时间复杂度也是 O(n^2),但空间复杂度为 O(1)。
|
1月前
|
存储 人工智能 算法
第十四届蓝桥杯C++B组编程题题目以及题解
第十四届蓝桥杯C++B组编程题题目以及题解
蓝桥杯备赛leetcode 70.爬楼梯,用最经典的题目来讲解动态规划
题目描述 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼梯顶部呢?
蓝桥杯备赛leetcode 70.爬楼梯,用最经典的题目来讲解动态规划
|
11月前
|
人工智能 移动开发 机器人
蓝桥杯AcWing 题目题解 - 二分与前缀和、差分
蓝桥杯AcWing 题目题解 - 二分与前缀和、差分
110 0
|
11月前
蓝桥杯AcWing 题目题解 - 递归与递推
蓝桥杯AcWing 题目题解 - 递归与递推
|
机器学习/深度学习 人工智能 安全
2023年第十四届蓝桥杯JavaB组省赛真题(题目+全部完整题解)2
2023年第十四届蓝桥杯JavaB组省赛真题(题目+全部完整题解)2
945 1
|
算法 前端开发
蓝桥杯 —— Web前端(算法类)【标题即题目链接,点击查看具体要求】
蓝桥杯 —— Web前端(算法类)【标题即题目链接,点击查看具体要求】
162 0
|
前端开发 算法
蓝桥杯 —— Web前端(页面布局类【Flex 布局】)【标题即题目链接,点击查看具体要求】
蓝桥杯 —— Web前端(页面布局类【Flex 布局】)【标题即题目链接,点击查看具体要求】
176 0
|
JSON 前端开发 JavaScript
蓝桥杯 —— Web前端(数据交互类)【标题即题目链接,点击查看具体要求】
蓝桥杯 —— Web前端(数据交互类)【标题即题目链接,点击查看具体要求】
133 0
|
自然语言处理 JavaScript 前端开发
蓝桥杯 —— Web前端(功能实现类)【标题即题目链接,点击查看具体要求】
蓝桥杯 —— Web前端(功能实现类)【标题即题目链接,点击查看具体要求】
111 0