【OI做题记录】【BZOJ】【HAOI2007】反素数ant

13 篇文章 0 订阅
2 篇文章 0 订阅

试题编号:BZOJ1053

对于任何正整数x,其约数的个数记作g(x)。例如g(1)=1、g(6)=4。如果某个正整数x满足:g(x)>g(i) 0<i<x
,则称x为反质数。例如,整数1,2,4,6等都是反质数。现在给定一个数N,你能求出不超过N的最大的反质数么

输入描述

一个数N(1<=N<=2,000,000,000)。

输出描述

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

输入样例

1000

输出样例

840


试题分析

这道题实际上是求1~n中因数最多的数中最小的。(仔细思考,这里不证明)
因为每个数是由几个质数相乘得到的(质数是相乘构成数的最小单位)
所以我们可以用前几个质数(12个就够了)构建反素数。
每个数A=2^p1+3^p2+5^p3……
因数个数cnt=(p1+1)*(p2+1)*(p3+1)*……

我们构建其中因数最多的。因数最多的取最小的。
但是p1,p2,p3等等的数怎么枚举呢?
我们发现,p1,p2,p3是严格不上升的。
证明:假如两个数,a^p1+b^p2,和a^p2+b^p1。a<b,p1>p2。两个数的因数个数相同,但是第一个比较小,所以选择第一个。
代码
不给你看
#include<cstdio>
#include<cstdlib>
#include<cstring>
long long n;
int ss[15]={-1,2,3,5,7,11,13,17,19,23,29,31,37};
long long ans_cnt=0,ans_sum=999999999;
void xfs(int x,long long cnt,long long sum,long long last)
{
	if(x>12)return;
		if(cnt>ans_cnt || (cnt==ans_cnt && sum<ans_sum))
		{
			ans_cnt=cnt;
			ans_sum=sum;
		}	
			int soy=1;
			for(int i=1;i<=last;i++)
			{
				if(sum*ss[x]>n)break;
				sum*=ss[x];
				xfs(x+1,cnt*(i+1),sum,i);
			}
}
int main()
{
	scanf("%I64d",&n);
	xfs(1,1,1,100000);
	printf("%I64d",ans_sum);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值