BZOJ 1053 浅谈正统素数的侧面反素数A.N.T.

这里写图片描述
世界真的很大
数的本质之类的东西,唯一分解定理
除了通过一个数来分解得到素数的唯一分解,通过枚举素数来反推原数也是常用的做法。
写的时候还是要注意细节,数论什么的一定要从数本身入手
讲道理其实解法最后和数论没有什么关系也没有什么关系

看题先:

description:

 对于任何正整数x,其约数的个数记作g(x)。例如g(1)=1、g(6)=4。如果某个正整数x满足:g(x)>g(i) 0

input:

一个数N(1<=N<=2,000,000,000)。

output:

不超过N的最大的反质数。

在一定范围内最大的反素数
仔细分析一下,反素数的因数个数必须要比比他小的数的个数多。
最大的反素数就是说,在这个区间内比他大的数的数的因数个数不会比他多,不然他就不是最大的了
比他小的数里面,也不会有数的因数比他多,因为他是“反素数”
即我们需要找的,就是在这样一个范围内,拥有最多素数个数的数

看到一个数的约数个数,一般能想到的就是这个约数个数定理吧:
这里写图片描述
然后这个约数个数定理是在一个数唯一分解之后才有的
而且发现质数的叠加的话最多也才12个就超过范围了
那我们直接枚举每一个质数的指数,来DFS暴力搜索就好

有一个剪枝是,大的质数的指数一定比小的质数的指数小,一个贪心的思想吧?

完整代码:

#include<stdio.h>
#include<algorithm>
using namespace std;
typedef long long dnt;

dnt n,ans=0,bns=0;
dnt p[13]={1,2,3,5,7,11,13,17,19,23,39,31};

void dfs(int state,dnt num,dnt tot,int last)
{
    if(num>n) return ;
    if(state==12)
    {
        if(tot>bns) bns=tot,ans=num;
        else if(tot==bns) ans=min(ans,num);
        return ; 
    }
    dnt rt=1;
    for(int i=0;i<=last;i++)
    {
        dfs(state+1,num*rt,tot*(i+1),i);
        rt*=p[state];
    }
}

int main()
{
    scanf("%lld",&n);
    ans=n;
    dfs(1,1,1,20);
    printf("%lld\n",ans);
    return 0;
}
/*
EL PSY CONGROO
*/

嗯,就是这样

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值