反素数概念及理解

关于反素数的概念参考题目链接

  • 素数是因子最少的数,那么反素数就是因子多的数,如果在一个数之前所有的数因子数量小于这个数的因子数量,那么这个数就是一个反素数
  • 那么怎么解这个问题呢?
    要求解这个问题,首先要知道几个结论,
  • 首先是唯一分解定理:任何数都可以拆成n个素数乘积的形式,且唯一
  • 如果一个数可以写成233251这种形式,那么它有多少个因子呢?根据排列组合的知识,可以明白是4*3*2=24个,也就是选择多少个2,多少个3,多少个5的问题
  • 将一个数的最小质因子按照从小到大的顺序排列起来,如果这个数是反素数。那么它们的指数应该是从大到小的。因为如果不是这样,那么它之前一定有某个数的因子数比它多,这样他就不是反素数了
    总结一下就是:x的因数应该最多,且如果存在因数相等的情况,那么x应该是最小的那一个(如果取大的那一个,那么就存在一个更小的数因数和它相等,这样不符合反素数严格大于的性质)
  • 如果理解了这样几个结论,那么对于这个问题,题目的n最大是2e9,这个数介于2的30次方和31次方之间,所以质因子指数和最大也就是30,可以使用搜索的方法进行爆搜,找到小于n的最大反素数,这需要记录当前找到的数的因子个数,从而不断更新答案
#include <iostream>
using namespace std;
int n;
typedef long long ll;
const int MAXN = 2e5 + 100;
int p[MAXN];
int vis[MAXN];
ll ans;
int num;//ans表示答案,num表示当前答案的因子数 
int prime;//质数个数 
int Prime(){
    
    
	int tot = 0;
	for(int i=2;i<=50;i++){
    
    
		if(!vis[i]) p[tot++] = i;
		for(int j=0;j<tot&&i*p[j]<=50;j++){
    
    
			vis[i*p[j]] = 1;
			if(i % p[j] == 0) break;
		}
	}
	return tot;
} 
void dfs(ll now, int number, int m){
    
    //now表示当前数是多少,number表示当前因数数量,m表示到第几个质数了 
	if(m >= prime) return;
	//因数数量小于当前显然需要更新为当前
	//如果因数个数和当前相等,那么答案应该更新为小的那一个(反素数因子个数严格大于前面的数的性质) 
	if(number > num || number == num && ans > now){
    
    
		ans = now;
		num = number;
	}
	for(int i=1;i<=31;i++){
    
    
		if(p[m] * now > n) break;
		now *= p[m];
		dfs(now, number * (i + 1), m + 1);//这里的number进行的改动就是在前面我说的排列组合
		//如果i为1,那么说明p[m]的指数为1,那么就有i+1=2种情况 
	}
}
int main(){
    
    
	prime = Prime();
	cin>>n;
	dfs(1, 1, 0);
	cout<<ans;	
	return 0;
}

如果还有问题可以看这个视频讲解

猜你喜欢

转载自blog.csdn.net/roadtohacker/article/details/114380415
今日推荐