AcWing 198. 反素数
练习题:
AcWing 199. 余数之和
扩展知识:
对于反素数:
- 1 ∼ N 1\sim N 1∼N中最大的反函数,就是 1 ∼ N 1 \sim N 1∼N中约数个数最多的数中最小的一个。
-
1
∼
N
1 \sim N
1∼N 中任何数的不同质因数都不会超过
10
10
10 个,且所有质因数的指数总和不超过30。
证明:
因为最小的那11个质因数的乘积2 * 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23 * 29 * 31 ≥ \geq ≥ 2 * 1 0 9 10^9 109,所以N不可能有多于10个不同的质因子。
又因为 2 31 > 2 ∗ 1 0 9 2^{31} > 2 * 10^9 231>2∗109,所以质因子的指数总和不可能超过30。 -
∀
x
∈
[
1
,
N
]
,
x
{\forall} x \in [1,N], x
∀x∈[1,N],x为反质数的必要条件是
x
x
x 可以写作
2
c
1
×
3
c
2
×
5
c
3
×
⋅
⋅
⋅
×
2
9
c
10
2^{c_1}\times3^{c_2}\times5^{c_3}\times···\times29^{c_{10}}
2c1×3c2×5c3×⋅⋅⋅×29c10,并且
c
1
≥
c
2
≥
c
3
≥
⋅
⋅
⋅
≥
c
10
≥
0
c_1 \geq c_2 \geq c_3 \geq ···\geq c_{10} \geq 0
c1≥c2≥c3≥⋅⋅⋅≥c10≥0。
通俗地讲: x x x 的质因子是连续的若干个最小的质数,并且指数单调递减。
思路:
请仔细看上面的知识点,很重要的,涉及到该题的思路。
因为要求给定的N的最小反素数,那么我们就进行dfs,只需要在遍历的时候加上上述的一些限制就可以大大的简短了代码量,然后按照第一个条件更新答案就好了。
需要满足的条件是:指数单调递减,总乘积不超过N,同时记录约数的个数。
代码实现:
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
int primes[10] = {2,3,5,7,11,13,17,19,23,29};
int len = 0,minx = 0,n;
void dfs(int u,int last,int s,int p)
{
if(s > len || s == len && p < minx)
{
len = s;
minx = p;
}
for(int i = 1; i <= last; i++)
{
if((ll)p * primes[u] > n) break;
p *= primes[u];
dfs(u + 1,i,s * (i + 1),p);
}
}
int main (void)
{
cin >> n;
dfs(0,30,1,1);
cout << minx << endl;
return 0;
}