数学结论【p1463】[POI2002][HAOI2007]反素数
Description
对于任何正整数x,其约数的个数记作g(x)。例如g(1)=1、g(6)=4。
如果某个正整数x满足:g(x)>g(i) 0<i<x,则称x为反质数。例如,整数1,2,4,6等都是反质数。
现在给定一个数N,你能求出不超过N的最大的反质数么?
Input
一个数N(1<=N<=2,000,000,000)。
Output
不超过N的最大的反质数。
woc,神仙题.
一.暴力\(O(n^{\frac{5}{2}})\) \(40pts\)
直接写暴力的话,可以\(get\)到\(40pts\)
暴力怎么写?
直接倒叙枚举\(n\),再判断当前\(i\)是否满足条件.(再枚举一层\(j\))
这样
for(R int i=n;i;i--)
{
R int res=calc(i);
bool flg=false;
for(R int j=1;j<i;j++)
if(res<=calc(j)){flg=true;break;}
if(!flg)
{
printf("%d",i);
break;
}
}
上面的\(calc\)函数是计算约数个数,\(\sqrt{n}\)的复杂度.
二,正解
还好突然想起来结论.
首先根据唯一分解定理
\[x=p_1^{k_1} \times p_2^{k_2} \times p_3^{k_3} \times \dots
\]
这里的\(p\)全部都是质数.
然后结论就是.
\[d(x)=(k_1+1)\times(k_2+1)\times \dots
\]
其实真正的定义的话,\(d(x)\)代表\(x\)的约数个数.
因此搜索就好了,枚举每一个质数的\(k\)次方,记录答案.
需要注意的是,当某一个数的约数个数之前已经出现过,那我们要取较为靠前的一个.
(因为题目要求必须严格\(>\))
代码
#include<cstdio>
#include<cctype>
#define int long long
#define R register
#define N 10000008
using namespace std;
inline void in(int &x)
{
int f=1;x=0;char s=getchar();
while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
while(isdigit(s)){x=x*10+s-'0';s=getchar();}
x*=f;
}
int prime[20]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59};
int ans,mx,n;
void dfs(int dep,int now,int cnt)
{
if(dep>=11)return;
if(cnt>mx)mx=cnt,ans=now;
if(cnt==mx and ans>now)ans=now;
for(R int i=1;i<=32;i++)
{
if(now*prime[dep]>n)break;
dfs(dep+1,now*=prime[dep],cnt*(i+1));
}
}
signed main()
{
in(n);
dfs(1,1,1);
printf("%lld",ans);
}
除特殊声明外,本博客作品均由顾z创作。
未经博主允许,不得转载