反素数
定义
-
对于正整数x,其约数的个数记作 g ( x ) g(x) g(x)。例如 g ( 1 ) = 1 g(1)=1 g(1)=1、 g ( 6 ) = 4 g(6)=4 g(6)=4。
-
如果某个正整数 x x x满足:对任意正整数 i ( 0 < i < x ) i(0<i<x) i(0<i<x),有 g ( x ) > g ( i ) g(x)>g(i) g(x)>g(i),那么 称 x x x为反素数。
感性理解,素数是只有1和本身两个约数,而反素数就是约数个数最多的数(并且在约数相同的情况下更小的那个数),所以反素数是对于一个范围而言的。
两个性质
根据唯一分解定理: x = p 1 k 1 p 2 k 2 p 3 k 3 . . . p n k n x = p_1^{k_1}p_2^{k_2}p_3^{k_3}...p_n^{k_n} x=p1k1p2k2p3k3...pnkn,x的因子个数是 ( k 1 + 1 ) ( k 2 + 1 ) . . . ( k n + 1 ) (k_1+1)(k_2+1)...(k_n+1) (k1+1)(k2+1)...(kn+1)。 假如 x x x是一个反素数,则:
- 质因子 p 1 , p 2 , p 3 . . p n p_1,p_2,p_3..p_n p1,p2,p3..pn是从2开始的连续的素数。
- 质因子的指数递减, k 1 ≥ k 2 ≥ . . . ≥ k n k_1\geq k_2\geq...\geq k_n k1≥k2≥...≥kn。
简单证明:
-
假设x是反素数,且质因子 p 1 , p 2 , p 3 . . p n p_1,p_2,p_3..p_n p1,p2,p3..pn不是从2开始的连续的素数。我们就可以把其中的某个素数换成更小的素数,但其指数不发生改变,这样我们就可以保证相同因子个数的情况下,存在一个更小的数,所以x不是反素数。直到交换到从2开始的连续的素数的时候才是最小的。
-
如果数值小的素数的幂次小于数值大的素数的幂,那么如果把这两个素数的指数交换,那么所得的 因子数量不变,但是得到的值变小,交换到最小的那个数时,质因子的指数一定是递减的。
例题:
题意:给出一个n,求不超过n的最大反素数是多少。
思路:根据性质,直接暴力深搜。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5+10;
const ll mod = 1e9+7;
int prime[] = {0, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31};
ll ans = 2e9+10, sum = 0, n;
//枚举当前是第几个质因子,v表示当前质因子的最大指数,now是当前数的大小,cnt表示数的因子个数。
void dfs(ll u, ll v, ll now, ll cnt) {
//更新ans,sum,得到答案。
if(cnt > sum) ans = now, sum = cnt;
if(cnt == sum) ans = min(ans, now);
//循环枚举每个质数的指数。
for(int i=1; i<=v; i++) {
if(now*prime[u] > n) break;
now *= prime[u];
//下一个质因子的指数小于等于i。
dfs(u+1, i, now, cnt*(i+1));
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
ll k = 0;
scanf("%lld", &n);
while((1ll<<k) <= n) k++;//找到2的最大次方,记得时1ll。
dfs(1, k, 1ll, 1ll);
printf("%lld", ans);
return 0;
}