D——简单数论
Description
定义:
设f(x)为x的约数个数
若对任意0<i<x都有f(i)<f(x),则称x为66数
给出一个正整数n,求出不大于n的最大66数
思路
(1):不同的质因子个数不会超过10,因为前10个质数的积为
2 ∗ 3 ∗ 5 ∗ 7 ∗ 11 ∗ 13 ∗ 17 ∗ 19 ∗ 23 ∗ 29 = 6 , 469 , 693 , 230 > 2 ∗ 1 0 9 2*3*5*7*11*13*17*19*23*29=6,469,693,230>2∗10^9 2∗3∗5∗7∗11∗13∗17∗19∗23∗29=6,469,693,230>2∗109
(2):质因子的个数总和不会超过31个,因为 2 31 > 2 ∗ 1 0 9 2^{31}>2*10^9 231>2∗109
(3):设一个数x的分解形式为 x = p 1 c 1 ∗ p 2 c 2 ∗ . . . ∗ p n c n x=p_1^{c_1}*p_2^{c_2}*...*p_n^{c_n} x=p1c1∗p2c2∗...∗pncn,则x的约数个数为 ( c 1 + 1 ) ∗ ( c 2 + 1 ) ∗ . . . ∗ ( c n + 1 ) (c_1+1)*(c_2+1)*...*(c_n+1) (c1+1)∗(c2+1)∗...∗(cn+1)。即每个质因数pi都有0~ci的指数选择。
然后我们发现,反素数其实就是 1~n 中 约数个数最多的数中最小的那个 (如果不是最小就意味着有一个比它小的数,约数个数和它一样,不符合小于的条件)。
那么我们要满足最小的原则,肯定是贪心啦。
假设我们取的质数从小到大,那么小数的数量一定要大于大数的数量,这样我们就可以满足最小了。
因为数据不大,我们使用深搜dfs搞定
转自人类高质量博客(这回扣的是大佬的啦QAQ)
代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long ll;
int n,p[10]={2,3,5,7,11,13,17,19,23,29};
ll pro=1,maxn,ans;
void dfs(int k,int pre,int tot)
{
if(k>=10) return;
if(tot>maxn||(tot==maxn&&pro<ans))
maxn=tot,ans=pro;
for(int i=0;i<=pre;i++)
{
ll temp=pow(p[k],i);
if(pro*temp>n) return;
pro*=temp;
dfs(k+1,i,tot*(i+1));
pro/=temp;
}
}
int main()
{
scanf("%d",&n);
dfs(0,30,1);
printf("%lld",ans);
return 0;
}