0x32反素数

数论部分还是代码好写而思考过程费劲,害

https://www.acwing.com/problem/content/description/200/

简言之就是求不超过N中约数个数最多的数中最小的一个

设所求为ans,即有大于ans的数都不是反质数

引理:
1~N中任何数的不同质因子都不会超过10个,且所有质因数的指数总和不超过30

2 * 3 * 5 * 7* 11 * 13 * 17 * 19 * 23 * 29 * 31> 2*\(10^{9}\)

\(2^{31}>2*10^{9}\)

引理2:任意x∈N,x为反素数的必要条件是:x分解质因数后可以写作\(2^{c1}*3^{c2}*5^{c3}*...*23^{c9}\),并且质数单调递减

这个的证明:就如果不递减的话,可以把一个大因数替换为小因数,新的数质因子数相同且数值最小,所以该数就不是答案

所以可以写一个dfs,爆搜+剪枝

#include<bits/stdc++.h>
#define ll long long
using namespace std;ll best=0,ans=0,n;
int primes[9]={2,3,5,7,11,13,17,19,23};
void dfs(int dep,ll tmp,ll num,int limit){
	if(dep>=10)return;//深度达到最大
	if(num>best||num==best&&ans>tmp){ans=tmp;
	best=num;
	} //更新答案 
	for(int i=1;i<=limit;i++){
		if((ll)tmp*primes[dep]>n)break;//剪枝 
		tmp*=primes[dep];
		dfs(dep+1,tmp,num*(i+1),limit);
	}
} 
int main(){
cin>>n;
dfs(0,1,1,30);
cout<<ans<<endl; 
return 0;} 


其他的反素数问题

https://codeforces.com/problemset/problem/27/E

这个数据有点大的离谱了吧~
在源代码上修改一下中止搜索条件,primes数组开大一点,再开一个unsigned long long就行了。

#include<bits/stdc++.h>
#define ll  unsigned long long
using namespace std;ll best=0,ans=1e18,n;
ll primes[16]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};
void dfs(int dep,ll tmp,ll num,int limit,int n){
	if(num>n)return;//深度达到最大
	if(dep>15)return;
	if(num==n&&ans>tmp){ans=tmp;} //更新答案 
	for(int i=1;i<=limit;i++){
		if((ll)tmp*primes[dep]>ans)break;//剪枝 
		tmp*=primes[dep];
		dfs(dep+1,tmp,num*(i+1),limit,n);
	}
} 
int main(){
cin>>n;
dfs(0,1,1,63,n);
cout<<ans<<endl; 
return 0;} 


posted @ 2022-03-24 08:56  misasteria  阅读(77)  评论(0编辑  收藏  举报