1:求某个数的素因子个数:
那么问题来了,对于已经的数我们怎么求比他小的最大素数呢
我们可以使用素数筛(不懂的同学可以百度一下)
然后用数组维护一下即可。
2:反素数。
首先 什么是反素数呢。
反素数的定义:对于任何正整数x,其约数的个数记做g(x).例如g(1)=1,g(6)=4.如果某个正整数x满足:对于任意i(0小于i小于x),都有g(i)小于g(x),则称x为反素数·
满足反素数有以下条件:
1.因子必须是连续的质因子
2.质因子的次数必须满足后一个比前一个的大
利用这些性质,我们可以很快求出反素数。
解释:
第一条:如果不是从2开始的连续素数,那么如果幂次不变,把素数变成数值更小的素数,那么此时因子个数不变,但是n的数值变小了。交换到从2开始的连续素数的时候n值最小。
第二条:如果数值小的素数的幂次小于数值大的素数的幂,那么如果把这两个素数交换位置(幂次不变),那么所得的n因子数量不变,但是n的值变小,直到符合条件。
由性质可知,我们进行反素数相关运算的方法是从小到大枚举每个质因子(素数)进行DFS
代码如下:
void dfs(ll num,int k,int sum,int limit) {
//num: 当前枚举到的数 k:枚举到的第k大的质因子 sum:该数的约数个数 limit:质因子个数上限(重要剪枝)
if(sum>maxsum) { //约数个数更多
maxsum=sum;
ans=num;
}
if(sum==maxsum&&ans>num) { //约数个数相同,把最优解更新为较小值
ans=num;
}
if(k>16) //这里k>x; x至少满足prime[1]*prime[2]*prime[3]*...*prime[x]>x ,当x=16时,数据已超过10^18
return; //当x=10时,数据已超过10^9
ll temp=num;
for(int i=1; i<=limit; i++) { //枚举每个质因子的个数
if(n/prime[k]<temp) //n为上限,用除法防止溢出
return;
temp*=prime[k];
dfs(temp,k+1,sum*(i+1),i); //把limit置为i的原因见性质第二条
}
}
感谢观看!