题目描述:
请你帮忙给从 1 到 n 的数设计排列方案,使得所有的「质数」都应该被放在「质数索引」(索引从 1 开始)上;你需要返回可能的方案总数。
让我们一起来回顾一下「质数」:质数一定是大于 1 的,并且不能用两个小于它的正整数的乘积来表示。
由于答案可能会很大,所以请你返回答案 模 mod 10^9 + 7 之后的结果即可。
示例 1:
输入:n = 5
输出:12
解释:举个例子,[1,2,5,4,3] 是一个有效的排列,但 [5,2,3,4,1] 不是,因为在第二种情况里质数 5 被错误地放在索引为 1 的位置上。
示例 2:
输入:n = 100
输出:682289015
提示:
1 <= n <= 100
解题思路1:关于本题的思考,我觉得应该分以下三步进行解题:
- 1.应该找出1-n中有多少质数
- 2.给非质数做全排列
- 3.排列完的值乘以质数的全排列
所遇问题1:我自认为由于数字庞大,所以可以利用到java当中的BigInteger类的方法进行计算,但是虽然通过了测试,但是导致运行效率太低,只有空间占用率达到100%,但是时间却只有百分之五;
public int numPrimeArrangements(int n) {
//首先要知道100以内哪些是质数
int[] flag = {0,1,1,0,1,0,1,0,0,0,
1,0,1,0,0,0,1,0,1,0,
0,0,1,0,0,0,0,0,1,0,
1,0,0,0,0,0,1,0,0,0,
1,0,1,0,0,0,1,0,0,0,
0,0,1,0,0,0,0,0,1,0,
1,0,0,0,0,0,1,0,0,0,
1,0,1,0,0,0,0,0,1,0,
0,0,1,0,0,0,0,0,1,0,
0,0,0,0,0,0,1,0,0,0};
BigInteger res = new BigInteger("1");
long t = (int)Math.pow(10,9)+7;
BigInteger math = new BigInteger(String.valueOf(t));
//求得非质数的个数
int add = 0;
for (int i = 0; i < n; i++) {
if(flag[i] == 1)
add++;
}
//求得质数的个数
int bdd = n-add;
//对非质数进行全排列
while (add > 1){
BigInteger temp = new BigInteger(String.valueOf(add));
res = res.multiply(temp);
add--;
}
//对质数进行全排列
while (bdd > 1){
BigInteger temp = new BigInteger(String.valueOf(bdd));
res = res.multiply(temp);
bdd--;
}
//将结果除以相应的数
res = res.remainder(math);
return res.intValue();
}
解题思路3:最后我在浏览解题评论区当中发现了超级优化的解题思路,原作者是这样解释他的思路的:代码详解
public int numPrimeArrangements(int n) {
int[] zhishu={
2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,
83,89,97
};
//计算质数个数
int nzhishu=0;
for(int c:zhishu){
if(n>=c){
nzhishu++;
}
}
//计算非质数的个数
int nfeizhishu=n-nzhishu;
long ans=1;
for(int i=nfeizhishu;i>1;i--){
ans=ans*i%1000000007;
}
for(int i=nzhishu;i>1;i--){
ans=ans*i%1000000007;
}
return (int)ans%1000000007;
}
代码理解:其实作者的思路和我一样,但是他没有利用BigInteger类进行大数相乘,而是直接将结果除以相应的值进行相加求和最后输出。
学习收获:
1.赋值:
BigInteger a=new BigInteger(“1”);
BigInteger b=BigInteger.valueOf(1);
2.运算:
① add(); 大整数相加
BigInteger a=new BigInteger(“23”);
BigInteger b=new BigInteger(“34”);
a. add(b);
②subtract(); 相减
③multiply(); 相乘
④divide(); 相除取整
⑤remainder(); 取余
⑥pow(); a.pow(b)=a^b
⑦gcd(); 最大公约数
⑧abs(); 绝对值
⑨negate(); 取反数
⑩mod(); a.mod(b)=a%b=a.remainder(b);
3.BigInteger构造函数:
一般用到以下两种:
BigInteger(String val);
将指定字符串转换为十进制表示形式;
BigInteger(String val,int radix);
将指定基数的 BigInteger 的字符串表示形式转换为 BigInteger
4.基本常量:
A=BigInteger.ONE 1
B=BigInteger.TEN 10
C=BigInteger.ZERO 0
5.n.compareTo(BigInteger.ZERO)==0 /相当于n == 0/
6.if(a[i].compareTo(n)>=0 &&a[i].compareTo(m)<=0) // a[i]>=n && a[i]<=m