反素数
题目描述
原题来自:POI 2001
如果一个大于等于 1 1 1 的正整数 n n n,满足所有小于 n n n 且大于等于 1 1 1 的所有正整数的约数个数都小于 n n n 的约数个数,则 n n n 是一个反素数。譬如: 1 , 2 , 4 , 6 , 12 , 24 1, 2, 4, 6, 12, 24 1,2,4,6,12,24,它们都是反素数。
请你计算不大于 n n n 的最大反素数。
输入
一行一个正整数 n n n。
输出
只包含一个整数,即不大于 n n n 的最大反素数。
样例
1000
840
提示
数据范围与提示:
对于 10% 的数据, 1 ≤ n ≤ 1 0 3 1≤n≤10^3 1≤n≤103 ;
对于 40% 的数据, 1 ≤ n ≤ 1 0 6 1≤n≤10^6 1≤n≤106 ;
对于 100% 的数据, 1 ≤ n ≤ 2 × 1 0 9 1≤n≤2×10^9 1≤n≤2×109 。
来源
一本通在线评测
想法
什么是反质数?
如果所有小于x
的数i
,数i
的约数个数=g[i]
都有g[i]<g[x]
,则x
是反素数。
1~n中最大的反素数等价于?
-
求1~n中最大的反素数
等价于: -
求1~n中约数最多的数中最小的数。
假设有2个约数最多的数x,y,g[x]=g[y]=10,
则更大的y因为x<y而g[x]!<g[y]而导致y不是反素数
首先,虽然n很大,但是反质数是一个很小的数。因为它要满足:
-
质因子次数单调递减。
-
质因子最大枚举到 28。
2 × 3 × 5 × 7 × 11 × 13 × 17 × 19 × 23 × 29 > 6 × 1 0 9 > 2 × 1 0 9 2 \times 3 \times 5 \times 7 \times 11 \times 13 \times 17 \times 19 \times 23 \times 29>6 \times 10^{9}>2 \times 10^{9} 2×3×5×7×11×13×17×19×23×29>6×109>2×109
-
单个质因子的次数最多为 30。
2 30 = 1 e 9 2^{30} = 1e9 230=1e9
采用上述三个性质,爆搜即可.找到哪个
#include<iostream>
using namespace std;
typedef long long LL;
int n;
int number;//number为约数个数最多的数的约数个数 == 最大反素数
int maxd;//maxd记录当前最大约数个数的数的约数个数 == 小于最大反素数位数个数
int primes[9] = {2, 3, 5, 7, 11, 13, 17, 19, 23};
//u是当前枚举到第u个素数, last是前一个素数所枚举的次数
//爆搜到p了, s是p之前所有约数个数之和
void dfs(int u,int last,int p,int s)
{//如果当前约数个数>最大约数个数 || 当前约数个数==最大约数个数且 当前数更小
if(s>maxd||s==maxd && p<number)
{
maxd=s;
//更新最大约数为s,约数最多的数中最小的数p
number = p;
}
if(u==9)return;//搜完了质数了
//枚举当前质数可用的次数
for(int i =1;i<=last;i++)
{
if((LL)p*primes[u]>n)break;
p*=primes[u];
//s*(i+1) 是约数个数的公式
dfs(u+1,i,p,s*(i+1));
}
}
int main(){
cin >> n;
dfs(0,30,1,1);
cout << number << endl;
return 0;
}