【阶段1】【反素数】合理转化问题+dfs

【题意】
对于任何正整数x,其约数的个数记作g(x),例如g(1)=1、g(6)=4。
如果某个正整数x满足:对于任意的小于x的正整数 i,都有g(x)>g(i) ,则称x为反素数。
例如,整数1,2,4,6等都是反素数。
现在给定一个数N,请求出不超过N的最大的反素数。
 
【输入格式】
一个正整数N。  
  
【输出格式】
一个整数,表示不超过N的最大反素数。  
  
【数据范围】
1≤N≤2∗10^9 
 
【输入样例】
1000  
 
【输出样例】
840

分析

  • 任何一个数都可以表示成若干素数的若干次方的乘积(x=c1^{n1}*c2^{n2}*c3^{n3}......*cm^{nm}
  • 根据乘法原理可以得知,这个数的所有约数(不管是质约数还是合约数)的个数就是:(n1+1)(n2+1)(n3+1)......(nm+1)
  • 根据反素数的定义,1~N中最大的反质数,就是1~N中约数个数最多的数中最小的一个.因为,如果不是最小的那一个,必然会出现g(x)=g(i)
  • 1~N中任何数的不同质因子都不会超过10个,因为2∗3∗5∗7∗11∗13∗17∗19∗23∗29∗31>2∗10^9
  • 2∗3∗5∗7∗11∗13∗17∗19∗23∗29∗31>2∗10^9,且所有质因数的指数总和不超过30,因为2^31>2∗10^9
  • x的质因子是连续的若干个最小的质数,且质数的指数单调递减.如果说我们选择的质数不是连续的,也就是A1∗A3那么我还不如选择A1∗A2因为这样数还更小.,如果说质数不是单调递减,c1<c2,那么那么C1跟C2交换会使得乘积更加小,而且约数个数不变(根据乘法的交换律可以得知)
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define INF 0xf0f0f0f
using namespace std;
typedef long long ll;
ll pri[21]={0,2,3,5,7,11,13,17,19,23,29};
inline ll read()
{
	char c=getchar();ll s=0,f=1;
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){s=s*10+c-'0';c=getchar();}
	return f*s;
}
ll n,tot[21];ll putout,ans;
inline void dfs(ll k,ll s,ll last,ll sum)
{
	if(sum>ans || (sum==ans && s<putout))
	{
		ans=sum;
		putout=s;
	}
	if(k>10 || last==0)return ;
	ll get=1;
	for(int i=0;i<=last;i++)//注意一定要从小到大,它不但可以防止爆炸,还可以节省时间 
	{
		if(s*get>n)return;
		tot[k]=i;
		dfs(k+1,s*get,i,sum*(i+1));
		tot[k]=0;
		get*=pri[k];
	}
}
int main()
{
	n=read();
	ans=0;
	dfs(1,1,30,1);
	printf("%lld\n",putout);
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值