这篇文章是帮一个叫做【废柴成长中】的孩子写的。
题目:
这里难点应该就是在【输入为一行用空格分开的整数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】正确