[POI2001] [HAOI2007] 反素数
题目描述
对于任何正整数 x x x,其约数的个数记作 g ( x ) g(x) g(x)。例如 g ( 1 ) = 1 g(1)=1 g(1)=1, g ( 6 ) = 4 g(6)=4 g(6)=4。
如果某个正整数 x x x 满足: ∀ 0 < i < x \forall 0 \lt i \lt x ∀0<i<x,都有 g ( x ) > g ( i ) g(x) \gt g(i) g(x)>g(i),则称 x x x 为反质数。例如,整数 1 , 2 , 4 , 6 1,2,4,6 1,2,4,6 等都是反质数。
现在给定一个数 N N N,你能求出不超过 N N N 的最大的反质数么?
输入格式
一个数 N N N。
输出格式
不超过 N N N 的最大的反质数。
样例 #1
样例输入 #1
1000
样例输出 #1
840
提示
1 ≤ N ≤ 2 × 1 0 9 1 \leq N \leq 2 \times 10^9 1≤N≤2×109
分析:
由于质因数分解定理:
设
x
=
∏
i
=
1
m
p
i
k
i
,
p
i
∈
P
设x=\prod_{i=1}^mp_i^{k_i},p_i \in P
设x=i=1∏mpiki,pi∈P
则根据乘法原理:
g
(
x
)
=
∏
i
=
1
m
(
k
i
+
1
)
g(x)=\prod_{i=1}^m(k_i+1)
g(x)=i=1∏m(ki+1)
由此可以看出反素数
x
的
p
i
是单增的,那么
k
i
一定是不升的
由此可以看出反素数x的p_i是单增的,那么k_i一定是不升的
由此可以看出反素数x的pi是单增的,那么ki一定是不升的
证明如下:
证明:
即
x
=
∏
i
=
1
m
p
i
k
i
,
p
i
∈
P
中
即x=\prod_{i=1}^mp_i^{k_i},p_i \in P中
即x=i=1∏mpiki,pi∈P中
存在
p
1
<
p
2
<
…
<
p
m
,
k
1
≥
k
2
≥
…
≥
k
m
存在p_1<p_2<…<p_m ,k_1\ge k_2\ge…\ge k_m
存在p1<p2<…<pm,k1≥k2≥…≥km
设
k
1
<
k
2
,
x
1
=
p
1
k
2
∗
p
2
k
1
…
∗
p
m
k
m
=
(
p
1
p
2
)
k
1
∗
p
1
k
2
−
k
1
∗
.
.
.
设k_1<k_2,x_1=p_1^{k2} * p_2^{k1} … *p_m^{km}=(p_1p_2)^{k1} * p_1^{k2-k1}*...
设k1<k2,x1=p1k2∗p2k1…∗pmkm=(p1p2)k1∗p1k2−k1∗...
又因为
x
2
=
p
1
k
1
∗
p
2
k
2
∗
.
.
.
∗
p
m
k
m
=
(
p
1
p
2
)
k
1
∗
p
2
k
2
−
k
1
∗
…
又因为 x_2=p_1^{k1}*p_2^{k2}*...*p_m^{km}=(p_1p_2)^{k1} * p_2^{k2-k1}* …
又因为x2=p1k1∗p2k2∗...∗pmkm=(p1p2)k1∗p2k2−k1∗…
可知
x
1
<
x
2
且约数个数相等,所以
x
2
必然不是反素数
可知x_1<x_2且约数个数相等,所以x_2必然不是反素数
可知x1<x2且约数个数相等,所以x2必然不是反素数
code:
#include<bits/stdc++.h>
using namespace std;
#define i64 long long
#define pii pair<i64,i64>
#define il inline
#define re register
const i64 MAXN=1e7+5;
int n;
i64 p[]={0,2,3,5,7,11,13,17,19,23,29};//素数表
i64 tot;
pii a[MAXN];
//dfs
il void dfs(i64 k,i64 last,i64 pi,i64 g)//k:第几个质数 last:上一个质数的指数 pi:当前的因数 g:当前约数的个数
{
a[++tot]=make_pair(pi,g);//存(i,g(i))
if(k>9) return;
for(re int j=1;j<=last;j++)//指数不升
{
if(pi*p[k]>n) break;
pi*=p[k];
dfs(k+1,j,pi,g*(j+1));
}
}
//
int main()
{
cin>>n;
dfs(1,100,1,1);
sort(a+1,a+1+tot);
int ans=a[1].first,maxn=a[1].second;
for(re int i=2;i<=tot;i++) if(a[i].second>maxn) {ans=a[i].first;maxn=a[i].second;}
cout<<ans;
return 0;
}
ps:
由于数据量只有2e9,而前10个素数的乘积已经大于2e9了,所以只考虑前10个素数即可