一、题目链接
二、题目大意
设函数 f ( x ) f(x) f(x)表示 x x x的约数个数。对于一个正整数 x x x,若满足任意 0 < i < x 0<i<x 0<i<x,都有 f ( x ) f(x) f(x)大于 f ( i ) f(i) f(i)。那么称 x x x为反质数。现给定数 N N N,找到 1 ∼ N 1 \sim N 1∼N中最大的反质数。
数据范围: 1 ≤ N ≤ 2 × 1 0 9 1 \leq N \leq 2 \times 10^9 1≤N≤2×109。
三、题目分析
首先, 1 ∼ N 1 \sim N 1∼N的最大反质数一定是 1 ∼ N 1 \sim N 1∼N中约数个数最多的数中最小的一个。下面给出证明:
- 设这个数为 x x x,因为 f ( x ) f(x) f(x)最大是函数 g g g的最大值,且 x x x是最小的那一个,所以小于 x x x的数的 f ( i ) < f ( x ) f(i)<f(x) f(i)<f(x)成立,所以 x x x为反质数。
- 因为 f ( x ) f(x) f(x)最大是函数g的最大值,且 x x x是最小的那一个,所以大于 x x x的数的 f ( i ) ≤ f ( x ) f(i) \leq f(x) f(i)≤f(x)成立,所以大于 x x x的所有数一定不是反质数。
x x x为反质数的必要条件是: x x x分解质因数后可以写成 2 c 1 × 3 c 2 × 5 c 3 × 7 c 4 × 1 1 c 5 × 1 3 c 6 × 1 7 c 7 × 1 9 c 8 × 2 3 c 9 × 2 9 c 10 2^{c_1} \times 3^{c_2} \times 5^{c_3} \times 7^{c_4} \times 11^{c_5} \times 13^{c_6} \times 17^{c_7} \times 19^{c_8} \times 23^{c_9} \times 29^{c_{10}} 2c1×3c2×5c3×7c4×11c5×13c6×17c7×19c8×23c9×29c10。并且 c 1 ≥ c 2 ≥ c 3 ≥ c 4 ≥ c 5 ≥ c 6 ≥ c 7 ≥ c 8 ≥ c 9 ≥ c 10 c_1 \geq c_2 \geq c_3 \geq c_4 \geq c_5 \geq c_6 \geq c_7 \geq c_8 \geq c_9 \geq c_{10} c1≥c2≥c3≥c4≥c5≥c6≥c7≥c8≥c9≥c10。下面给出证明:
- 反证法:若存在质因数分解中有一项 p k ( p > 29 ) p^k(p>29) pk(p>29),则必定有不超过 29 29 29的质因子 p ′ p' p′不能整除 x x x。显然 x / p k × p ′ k x/p^k \times p'^k x/pk×p′k的约数个数和 x x x相同,但 x / p k × p ′ k < x x/p^k \times p'^k<x x/pk×p′k<x所以根据 1 1 1,发现与定义矛盾,所以质因数一定小于 29 29 29。
- 反证法:若 x x x的质因数不是连续的,同上用 p ′ k ′ p'^{k'} p′k′代替最大的质因数 p p p的项 p k p^k pk得到更小的值,与定义矛盾。
- 反证法:若 x x x的质因数的指数不单调递减,则一定有相邻两项 p 1 a × p 2 b p_1^a \times p_2^b p1a×p2b满足 p 1 < p 2 p_1<p_2 p1<p2,且 a > b a>b a>b。而同上替换为 p 1 b × p 2 a p_1^b \times p_2^a p1b×p2a,一定更小,且约数数目相同。与定义矛盾。
综上所述,我们只需要 D F S DFS DFS搜索答案即可,因为实际上的搜索范围很小,所以并不会超时。
四、正解程序
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll maxn=100010;
ll prime[maxn/10],count1=0,n;
bool vis[maxn];
void oula()
{
memset(vis,false,sizeof(vis));
for(ll i=2;i<=maxn-10;i++)
{
if(!vis[i])
prime[++count1]=i;
for(ll j=1;j<=count1 && prime[j]*i<=maxn-10;j++)
{
vis[prime[j]*i]=true;
if(i%prime[j]==0)
break;
}
}
}
ll ans=0x7fffffff,Max=-1;
void dfs(ll k,ll val,ll last,ll times)
{
if(k>16)
return;
if(Max<times)
{
Max=times;
ans=val;
}
else if(Max==times)
ans=min(val,ans);
for(ll i=1;i<=last;i++)
{
ll temp=val*prime[k];
if(temp>n)
return;
dfs(k+1,temp,i,times*(i+1));
val*=prime[k];
}
}
int main()
{
oula();
scanf("%lld",&n);
dfs(1,1,100,1);
printf("%lld\n",ans);
return 0;
}