P1463 反素数

[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

分析

首先考虑 g(x) 的求法:
设 x = ∏ p i k i 设 x = \prod p^{k_i}_i x=piki 则 g ( x ) = ∏ k i + 1 ,其中 p i ∈ P 则 g(x) =\prod k_i+1,其中p_i \in P g(x)=ki+1,其中piP
比如12,可以写为 12 = 2 2 ⋅ 3 , 12=2^2 \cdot 3, 12=223, g ( 12 ) = 3 ∗ 2 = 6 g(12)=3*2=6 g(12)=32=6
证明:乘法原理
所以对于一个反素数 x,假设 p i p_i pi 是单增的,那么 k i k_i ki 必须不升

代码

#include<bits/stdc++.h>
using namespace std;
int p[] = {0,2,3,5,7,11,13,17,19,23,29};
int tot = 0,n;
pair<int, int> a[1000000];
void dfs(int i, int last, int pi,int k) {
	a[++tot] = make_pair(pi, k);
	if (i > 9) return;
	else {
		int pp = p[i];
		for (int j = 1; j <= last; j++) {
			if (1ll * pi* pp > n) break;
			pi *= pp;
			dfs(i + 1, j, pi, k * (j + 1));
		}
	}
	return;
}
signed main() {
	cin >> n; dfs(1, 100, 1, 1);
	sort(a + 1, a + tot + 1);
	int maxn = a[1].second,ans=a[1].first;
	for (int i = 2; i <= tot; i++) {
		if (a[i].second > maxn) {
			maxn = a[i].second;
			ans = a[i].first;
		}
	}
	cout << ans;
	return 0;
}

分析

只要把可能是反素数的数筛出来,在判断就可以了,怎么筛可以参考上面的分析
这里需要注意下

	int maxn = a[1].second,ans=a[1].first;
	for (int i = 2; i <= tot; i++) {
		if (a[i].second > maxn) {
			maxn = a[i].second;
			ans = a[i].first;
		}
	}
	cout << ans;

取走最大值不一定选个-1或-INF作为初始值。可以采用以上方法,在别的题目中,取-1仍存在风险,可能-1比正确答案还大

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值