问题描述:
将一个数N分为多个正整数之和,即N=a1+a2+a3+…+ak,定义M=a1*a2*a3*…*ak为N的潜能。
给定N,求它的潜能M。
由于M可能过大,只需求M对5218取模的余数。
输入格式:
输入共一行,为一个正整数N。
输出格式:
输出共一行,为N的潜能M对5218取模的余数。
样例输入:
10
样例输出:
36
数据规模和约定:
1<=N<10^18
思路:
观察题目我们可以举出如下几个例子:
N = 4 = 2 + 2 N = 5 = 3 + 2 N = 6 = 3 + 3 N = 7 = 3 + 2 + 2
N = 8 = 3 + 3 + 2 + 2 .... N= 10 = 3 + 3 + 2 + 2 N = 11 = 3 + 3 + 3 + 2 + 2
不难发现,我们可以从中总结出规律来:
当N <= 2 时,最大的M其实就是自己本身,即使题目提到说一个正整数可以分解为多个,但是对二来说如果分解成为1+1的话,那么其M将不会是最大的那个值。
当 N >= 3时,N % 3 == 0, 其可以分解为 N / 3 个 3 相乘。
N % 3 == 1, 其可以分解为 (N / 3 - 1)个 3与 两个 2 相乘。
N % 3 == 2, 其可以分解为 N / 3 个 3与 以一个 2 相乘。
注解:而为什么不分解成为其他数相乘呢,首先其他数可以分解成2和3的形式,其次2和3相同项相乘,其实就是幂的乘积,初中知识我们可以直到幂的乘积可以达到很大的值的,但是如果分解成为含有1的相乘的话,那就没有太大的意义了。反而导致整体的乘积变小。
关于求幂之积,我首先就想到了java内置包中的Math类的pow方法,但是他实际返回的是一个double类型的数据,如果强制转换成为int行,也会损失精度。(此时你可能回想,都是正整数相乘,不会出先小数点后不是0的想象,转换也没有什么关系,但是题目实际也说到了,如果相乘的结果才去取模的话,数值可能会很大,甚至出现数据溢出的情况,毕竟你调试是没有反馈回来的,哪怕你用到java中的BigInteger类的话,也可能会出现运算超时 的情况了,因此我们应该采用,每累乘一次就对当前数值进行取模,这样运算效率就会大大的提高了)
说到运算的效率,就不得不提及到快速幂的算法了
不清楚什么是快速幂算法的小伙伴可以看看这个:http://t.csdn.cn/Wl4NV
快速幂的相关代码:
public static long fastPower(long base, long power) {
long result = 1;
while (power > 0) {
if ((power & 1) == 1) {
result = result * base % 5218;
}
power >>= 1;
base = (base * base) % 5218;
}
return result;
}
base:底数 power :指数 result : 用来存储当前的数值的取模值
power & 1:这个是位运算符,表示power转换成2进制的形式与1的二进制数:00000001相与,如果为1则说明power为奇数,如果为0则说明power为偶数。
power >>= 1: 表示power转换成2进制的形式后向右移动1位,相当于原十进制数除2
当指数为奇数时,抽底数相同的一类组合出来,然后指数边为原来的一半(9 / 2 = 4)
如:3^10 = 3*3*3*3*3*3*3*3*3*3 10个3
=(3*3)*(3*3)*(3*3)*(3*3)*(3*3) 5 个(3*3)= 9^5
=(3*3*3*3)*(3*3*3*3) 因为这个时候指数变成奇数,所以又提出了一个(3*3)出去 因此 2个(3*3*3*3) = 81 ^ 2
= (3*3*3*3*3*3*3*3) = 6561^1
完整代码:
import java.util.Scanner;
/**
* @author Qik~
* @create 2023-01-15 12:58
*/
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
long N = scan.nextLong();
int goal = 0;
long M = 0;
if (N <= 2) {
System.out.println(N);
} else {
goal = (int) (N % 3);
if (goal == 0) {
M = fastPower(3,(N / 3));
System.out.println(M);
} else if (goal == 1) {
M = fastPower(3,(N / 3 - 1)) * 4 % 5218;
System.out.println(M);
} else if (goal == 2) {
M = fastPower(3,(N / 3)) * 2 % 5218;
System.out.println(M);
}
}
}
public static long fastPower(long base, long power) {
long result = 1;
while (power > 0) {
if ((power & 1) == 1) {
result = result * base % 5218;
}
power >>= 1;
base = (base * base) % 5218;
}
return result;
}
}