想打表的自行离开
题目描述
对于任何正整数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; }