洛谷 P1463、POI2002、HAOI2007 反素数

想打表的自行离开

题目描述

对于任何正整数x,其约数的个数记作g(x)。例如g(1)=1、g(6)=4。

如果某个正整数x满足:g(x)>g(i) 0<i<x,则称x为反质数。例如,整数1,2,4,6等都是反质数。

现在给定一个数N,你能求出不超过N的最大的反质数么?

不能

题意:

求最小的x∈[1,N],使得x为  g(x)最大的数  中最小的一个。

 1.x不会有超过10个不同质因子。理由:2*3*5...*31>2*1e9,2*3*5...*29<2*1e9。2~29质数刚好10个。

 2.质因子指数不会大于30。理由:当取最小的质因子2时,231>2*1e9,230<2*1e9。

 3.若x=p1^c1*p2^c2...pn^cn,则x的因子个数为(c1+1)(c2+1)...(cn+1)。即:g(x)=(c1+1)(c2+1)...(cn+1)。

 4.质因子连续、指数不升。理由:反证法。若x=p1^c1*p2^c2...pn^cn,且存在pn-1<p<pn,则x0=p1^c1*p2^c2...pn-1^cn-1*p^cn<x,g(x0)=g(x),不符合题意。

                   若存在cn>cn-1,则将cn,cn-1位置交换,也不符合题意

综上所述,可以用上述几个约束条件进行搜索剪枝。

代码就是简单的DFS。

#include<iostream>
#include<vector>
typedef long long ll;
using namespace std;
const ll pa[16]={0,2,3,5,7,11,13,17,19,23,29};
ll n,ans=1,g=0;

void dfs(ll p,ll t,ll now,ll ng)
{
    if(now>n) return;
    if(p>10) return;
    ll temp=ng;
    for(ll i=1;i<=t;i++){
        now*=pa[p];
        ng=temp*(i+1);
        if(now>n) return;
        if(ng>g) ans=now,g=ng;
        if(ng==g) ans=min(now,ans);
        dfs(p+1,i,now,ng);
    }
}

signed main()
{
    cin>>n;
    dfs(1,30,1,1);
    cout<<ans;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ehznehc/p/10294383.html