题目要求
请找出<=n范围内,使得所有的「质数」,并且将质数放到「质数索引」(索引从 1 开始)上;你需要返回可能的方案总数。
由于答案可能会很大,所以请你返回答案 模 mod 10^9 + 7 之后的结果即可。
示例 1:
输入:5
输出:12
解释:从1到5的质数有[2,3,5],需要对这个数据做排列组合,质数3个,非质数2个;放在质数索引上排列数是3*2*1,非质数排列数是2*1;总数就是:3*2*1*2*1=12次
解题思路
1. 先提供判断是否为质数的方法; 这里我使用的判断方式是从2计算到Math.sqrt(n) 也就是n的平方根来计算;
2. 调用判断质数的方法获取质数数量; 这里我根据经验提前统计了从1到28每个区间段的质数数量,这个可以加快计算,超过28之后再做质数计算。
3. 使用排列组合公式进行计算:count ! * (n-count) ! 也就是 count的阶乘 乘以 n-count的阶乘;这块属于高中数学知识,如果还能记住,这个题会快很多。
代码实现
class Solution {
int mod = 1000000000+7;
public int numPrimeArrangements(int n) {
int count = countPrime(n);
int left = n - count;
long result = 1;
for(int i=2;i<=count;i++) {
result = (result % mod) * i % mod;
}
for(int j=2;j<=left;j++) {
result = (result % mod) * j % mod ;
}
return (int)result;
}
int countPrime(int n) {
if(n== 1) {
return 0;
}
if(n==2) {
return 1;
}
if(n<=4) {
return 2;
}
if(n<=6) {
return 3;
}
if(n<=10) {
return 4;
}
if(n<=12) {
return 5;
}
if(n<=16) {
return 6;
}
if(n<=18) {
return 7;
}
if(n<=22) {
return 8;
}
if(n<=28) {
return 9;
}
int count = 9;
for(int i=29;i<=n;i++) {
if(isPrime(i)) {
count++;
}
}
return count;
}
boolean isPrime(int n) {
int v = (int) Math.sqrt(n);
for(int i=2;i<=v;i++) {
if(n%i==0) {
return false;
}
}
return true;
}
}
总结
这道题是一个简单的质数计算+数学的排列组合,这个过程中容易出现问题的是数据的越界问题,这里我使用long来记录结果,最终强制转换成int,这样就给出了结果。