P1463 [POI2001] [HAOI2007] 反素数

[POI2001] [HAOI2007] 反素数

题目描述

对于任何正整数 x x 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 满足: ∀ 0 < i < x \forall 0 \lt i \lt x ∀0<i<x,都有 g ( x ) > g ( i ) g(x) \gt g(i) g(x)>g(i),则称 x x x反质数。例如,整数 1 , 2 , 4 , 6 1,2,4,6 1,2,4,6 等都是反质数。

现在给定一个数 N N N,你能求出不超过 N N N 的最大的反质数么?

输入格式

一个数 N N N

输出格式

不超过 N N N 的最大的反质数。

样例 #1

样例输入 #1

1000

样例输出 #1

840

提示

1 ≤ N ≤ 2 × 1 0 9 1 \leq N \leq 2 \times 10^9 1N2×109

分析:

由于质因数分解定理: 设 x = ∏ i = 1 m p i k i , p i ∈ P 设x=\prod_{i=1}^mp_i^{k_i},p_i \in P x=i=1mpiki,piP
则根据乘法原理: g ( x ) = ∏ i = 1 m ( k i + 1 ) g(x)=\prod_{i=1}^m(k_i+1) g(x)=i=1m(ki+1)
由此可以看出反素数 x 的 p i 是单增的,那么 k i 一定是不升的 由此可以看出反素数x的p_i是单增的,那么k_i一定是不升的 由此可以看出反素数xpi是单增的,那么ki一定是不升的

证明如下:

证明:

即 x = ∏ i = 1 m p i k i , p i ∈ P 中 即x=\prod_{i=1}^mp_i^{k_i},p_i \in P中 x=i=1mpiki,piP
存在 p 1 < p 2 < … < p m , k 1 ≥ k 2 ≥ … ≥ k m 存在p_1<p_2<…<p_m ,k_1\ge k_2\ge…\ge k_m 存在p1<p2<<pm,k1k2km
设 k 1 < k 2 , x 1 = p 1 k 2 ∗ p 2 k 1 … ∗ p m k m = ( p 1 p 2 ) k 1 ∗ p 1 k 2 − k 1 ∗ . . . 设k_1<k_2,x_1=p_1^{k2} * p_2^{k1} … *p_m^{km}=(p_1p_2)^{k1} * p_1^{k2-k1}*... k1<k2x1=p1k2p2k1pmkm=(p1p2)k1p1k2k1...
又因为 x 2 = p 1 k 1 ∗ p 2 k 2 ∗ . . . ∗ p m k m = ( p 1 p 2 ) k 1 ∗ p 2 k 2 − k 1 ∗ … 又因为 x_2=p_1^{k1}*p_2^{k2}*...*p_m^{km}=(p_1p_2)^{k1} * p_2^{k2-k1}* … 又因为x2=p1k1p2k2...pmkm=(p1p2)k1p2k2k1
可知 x 1 < x 2 且约数个数相等,所以 x 2 必然不是反素数 可知x_1<x_2且约数个数相等,所以x_2必然不是反素数 可知x1<x2且约数个数相等,所以x2必然不是反素数

code:

#include<bits/stdc++.h>
using namespace std;
#define i64 long long 
#define pii pair<i64,i64> 
#define il inline
#define re register
const i64 MAXN=1e7+5;
int n;
i64 p[]={0,2,3,5,7,11,13,17,19,23,29};//素数表
i64 tot;
pii a[MAXN];

//dfs
il void dfs(i64 k,i64 last,i64 pi,i64 g)//k:第几个质数   last:上一个质数的指数   pi:当前的因数   g:当前约数的个数 
{
	a[++tot]=make_pair(pi,g);//存(i,g(i)) 
	if(k>9) return;
	for(re int j=1;j<=last;j++)//指数不升 
	{
		if(pi*p[k]>n) break;
		pi*=p[k];
		dfs(k+1,j,pi,g*(j+1));
	}
}
//

int main()
{
	cin>>n;
	dfs(1,100,1,1);
	sort(a+1,a+1+tot);
	int ans=a[1].first,maxn=a[1].second;
	for(re int i=2;i<=tot;i++) if(a[i].second>maxn) {ans=a[i].first;maxn=a[i].second;}
	cout<<ans; 
	return 0;
}

ps:

由于数据量只有2e9,而前10个素数的乘积已经大于2e9了,所以只考虑前10个素数即可

end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值