任
何
小
于
的
正
数
的
约
数
个
数
都
小
于
的
约
数
个
数
,
在
一
个
集
合
中
,
因
素
最
多
并
且
值
最
小
的
数
,
就
是
反
素
数
。
任何小于 的正数的约数个数都小于 的约数个数\,,在一个集合中,因素最多并且值最小的数,就是反素数。
任何小于的正数的约数个数都小于的约数个数,在一个集合中,因素最多并且值最小的数,就是反素数。
反
素
数
有
这
样
的
性
质
:
反素数有这样的性质:
反素数有这样的性质:
- p 一 定 是 从 2 开 始 的 连 续 素 数 p一定是从2开始的连续素数 p一定是从2开始的连续素数
- n = p 1 k 1 ∗ p 2 k 2 ∗ . . . ∗ p n k n , k 1 ≥ k 2 ≥ . . . ≥ k n n=p_1^{k_1}*p_2^{k_2}*...*p_n^{k_n},k_{1} \geq k_2\geq...\geq k_n n=p1k1∗p2k2∗...∗pnkn,k1≥k2≥...≥kn
简 单 证 明 : 简单证明: 简单证明:
-
如果不是从2开始的连续素数,那么如果幂次不变,p因子更小,则n更小。
-
如果数值小的素数的幂次小于数值大的素数的幂,那么如果把这两个素数交换位置(幂次不变),那么因子数量不变,但是n的数值更小。
注
意
:
注意:
注意:
1.
p
应
该
枚
举
的
范
围
∏
p
i
≤
n
,
通
常
情
况
下
n
<
=
1
0
18
,
有
16
个
质
数
p应该枚举的范围 \prod p_i\leq n,通常情况下n<=10^{18},有16个质数
p应该枚举的范围∏pi≤n,通常情况下n<=1018,有16个质数
2.
最
高
次
应
该
为
2
64
,
即
64
次
方
最高次应该为2^{64},即64次方
最高次应该为264,即64次方
3.
对
于
n
=
p
1
k
1
∗
p
2
k
2
∗
.
.
.
∗
p
n
k
n
,
k
1
≥
k
2
≥
.
.
.
≥
k
n
,
因
子
的
个
数
为
(
1
+
k
1
)
(
1
+
k
2
)
.
.
.
(
1
+
k
n
)
对于n=p_1^{k_1}*p_2^{k_2}*...*p_n^{k_n},k_{1} \geq k_2\geq...\geq k_n, 因子的个数为(1+k_1)(1+k_2)...(1+k_n)
对于n=p1k1∗p2k2∗...∗pnkn,k1≥k2≥...≥kn,因子的个数为(1+k1)(1+k2)...(1+kn)
4.可以用dfs求解,可以用剪枝的技巧来优化(可行性剪枝,最优化剪枝)
常
见
题
型
:
常见题型:
常见题型:
1.求因子数一定的最小数 CF27E
2.求 n 以内因子数最多的数ZOJ2562
这道题要求的是n以内因子数最多的最小数和cf27e同理
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
using namespace std;
typedef unsigned long long ull;
ull n;
ull ans=0;
ull ans_num=0;
ull p[16]= {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53};
//第i个素数,积为now,有num个因子
void dfs(int pos,ull sum,ull num,int pre){
if(sum>n || pos>=16) return ;
if(ans_num<num){
ans_num=num;
ans=sum;
}
if(ans_num==num && sum<ans) ans=sum;
for(int i=1;i<=pre;i++){
if(p[pos]*sum>n) break;
dfs(pos+1,sum*=p[pos],num*(1+i),i);
}
return ;
}
int main(){
// freopen("input.in","r",stdin);
while(scanf("%llu",&n)!=EOF){
ans_num=0;
dfs(0,1,1,64);
// cout<<ans<<endl;
printf("%llu\n",ans);
}
return 0;
}