题目描述:
请你帮忙给从 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
解题思路:
常规类型的题目,但是在统计质数个数的时候,在Math.sqrt处理下可能也会出现timeout limit ,因此,此处使用 厄拉多塞筛法 进行一定范围内的质数的统计,具体算法相见代码。
同时,在进行mod操作时,mod操作具有交换律 (a*b*c)%m = a%m*b%m*c%m
掌握要点:
质数统计算法 厄拉多塞筛法
连乘中mod操作具有交换律
源码展示:
1 public int numPrimeArrangements(int n) { 2 3 if(n == 1 || n == 2){ 4 return 1; 5 } 6 7 //质数的个数 8 boolean[] sign = new boolean[n + 1 ]; 9 int primes_count = 0; 10 for(int i = 2; i <= n;i++){ 11 if(sign[i] == false){ 12 primes_count++; 13 for(int j = i + i;j <= n; j += i){ 14 sign[j] = true; 15 } 16 } 17 } 18 19 //求阶乘 20 int no_primes_count = n - primes_count; 21 int max = Math.max(no_primes_count,primes_count); 22 int min = Math.min(no_primes_count,primes_count); 23 24 //模运算复合交换律 25 long res = 1; 26 for(int i = 1;i <= max;i++){ 27 res *= i; 28 res %= 1000000007; 29 if(i <= min){ 30 res *= i; 31 res %= 1000000007; 32 } 33 } 34 return(int) res; 35 36 }