反素数

反素数的定义参考题目吧:题目链接

N以内的最大的反素数具有如下特征:

  1. 它是N以内约数个数最多的数字中最小的一个。对任意一个比它小的数字,约数个数没有它多,任何一个比它大的数字,约数数量不比它多,所以它就是反素数。
  2. 最小的连续11个质因子的连乘积大于N的最大值,因此不会是多余10个不同的质因子。
  3. 2 31 > N 2^{31}>N 231>N所以指数总和不超过31
  4. 如果 x x x是反素数, x x x的质因子是连续的若干个最小的质数,且指数单调递减。即可以写成: 2 c 1 ∗ 3 c 2 ∗ 5 c 3 ∗ 7 c 4 ∗ 1 1 c 5 ∗ 1 3 c 6 ∗ 1 7 c 7 ∗ 1 9 c 8 ∗ 2 3 c 9 ∗ 2 9 c 10 2^{c1}*3^{c2}*5^{c3}*7^{c4}*11^{c5}*13^{c6}*17^{c7}*19^{c8}*23^{c9}*29^{c10} 2c13c25c37c411c513c617c719c823c929c10并且 c 1 ≥ c 2 ≥ c 3 ≥ c 4 ≥ c 5 ≥ c 6 ≥ c 7 ≥ c 8 ≥ c 9 ≥ c 10 c1 \geq c2 \geq c3 \geq c4 \geq c5 \geq c6 \geq c7 \geq c8 \geq c9 \geq c10 c1c2c3c4c5c6c7c8c9c10如果有一项 p k ( p > 29 ) p^{k}(p > 29) pk(p>29),因为最小的连续11个质数的乘积超过了N的最大范围,因此如果有一项 p k ( p > 29 ) p^{k}(p >29) pk(p>29)那么一定有至少一个质数 z ( z ≤ 29 ) z(z \leq 29) z(z29),若将 p p p z z z代替,根据算术基本定理的推论( N 的 正 约 数 的 个 数 为 ( c 1 + 1 ) ∗ ( c 2 + 1 ) ∗ . . . ∗ ( c m + 1 ) , c 1 , c 2... c m 为 N 的 算 术 基 本 定 理 的 展 开 形 式 中 各 个 质 因 子 指 数 非 0 的 质 数 的 指 数 N的正约数的个数为(c1+1)*(c2+1)*...*(cm+1),c1,c2...cm为N的算术基本定理的展开形式中各个质因子指数非0的质数的指数 N(c1+1)(c2+1)...(cm+1),c1,c2...cmN0)(证明比较简单,可以自行考虑一下)替代完成后发现约数的个数没有发生变化,但是这个数字变小了,根据 1. 1. 1.可得这并不是一个最大反素数,因此不会有超过29的系数。
  5. 同理,如果指数不是单调递减的,我们只需要将指数按照从大到小的顺序分配给一个从小到大的质数序列,会得到一个更小的数字,但是约数个数和原来的数字相同,因此刚刚那个数字并不是最大反素数。因此指数都是递减的。

有了这些约束条件,我们可以通过dfs暴力枚举所有的情况,因为约束条件比较强,而且可以通过剪枝,提前去掉比如数值已经大于N的数字,所以时间复杂度还可以接受,可以AC。

#include <bits/stdc++.h>
using namespace std;
#define mem(a, b) memset(a, b, sizeof a)
int prime[] = {0, 2, 3, 5, 7, 11, 13, 17, 19, 23, 27, 29, 31};
int num[15];
typedef long long ll;
int n;
ll res, numbers;
void dfs(ll number, int m){
	if (m == 11){
		ll temp = 1;
		for (int i = 1; i <= 11; i++)temp = temp * (1 + num[i]);
		if (temp > numbers){
			numbers = temp;
			res = number;
		}
		else if (temp == numbers){
			res = min(res, number);
		}
		return;
	}
	ll t = 1;
	for (int i = 0; i <= num[m]; i++){
		num[m + 1] = i;
		if (number * t > n)return;
		dfs(number * t, m + 1);
		t = t * prime[m + 1];
	}
}
int main(){
	mem(num, 0);
	num[0] = 31;
	cin >> n;
	numbers = -1;
	res = -1;
	dfs(1, 0);
	printf("%lld\n", res);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值