反素数

最近才接触到反素数,放一个大佬的链接

反素数的概念:先定义g(x)为g的约数的个数,如12有1,2,3,4,6,12,所以g(12)=6。如果某个整数x满足:g(x)>g(i),i 取(0,x),那么x为反素数。
注:约数,因数,因子都是同一个概念。真因子就是在这个基础上除去本身。

任意一个合数都可以表示为素数的乘积形式:N=p1e1*p2e2*p3e3*p4e4
p1,p2,p3…为素数,e为自然数。如12=22*31 8=23
有一个结论就是N的因子个数就是(1+e1)*(1+e2)*(1+e3) *…

这些对理解反素数有很大的作用。反素数就是尽可能地让因子数量最大,但是数值最小。对于这个直接贪心地想就可以了,首先要让因子数量尽可能的多,只需要把质因数的次数变多,或者质因数变多。但是还得满足让数值尽可能的小,那么就要让小的质因数的次数尽可能的大,比如说12=2*2*3 18=2*3*3,显然它们的因子数目是相同的,但是12更优。
这解释的就是反素数的性质一:N=p1e1*p2e2*p3e3*p4e4…必然有e1>=e2>=e3>=e4…

性质二是:一个反素数的质因子必然是从2开始连续的质数
这个性质举个例子就可以理解了:6=2*3 10=2*5 6和10因子数目相同,显然6更小。直接跳过一个小一点的质数,放一个大的质数显然会使数值变得更大。

个人感觉求反素数算是一个暴搜,因为上面两个性质剪枝,不会存在超时的问题。

模板的话也没有什么复杂的东西,遇到不同的题稍微改一下就可以了。

void dfs(int dep,ll tmp,int num,int limit)//dep表示到第几个素数, 
{										 //tmp表示当前可能ans值,num表示因子数 
    if(dep>=16) return;//深度达到最大 
    if(num>best)//best记的是当前最优num,有更优就更新 
    {
        best=num;
        ans=tmp;
    }
    //当因子个数相同时,取值最小的
    if(num==best&&ans>tmp) ans=tmp;
    for(int i=1;i<=limit;i++)
    {
        if(n/p[dep]<tmp) break;
        dfs(dep+1,tmp*=p[dept],num*(i+1));
    }
}
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值