聪明的燕姿

link

一道……搜索题?

显然想到分解质因数。假如

\[m=\prod\limits_{i=1}^Np_i^{c_i} \]

那么它的因数和会等于

\[\prod\limits_{i=1}^N\sum\limits_{j=0}^{c_i}p_i^j \]

很基础。然后可以想到把原数分解成一些类似于上文后面和的乘机,每一种合法的分解都对应一个合法的配对数字。然后呢?

卡在这里了。看了一眼题解,说爆搜。

那就没什么好说的了,除了我发现我不怎么会剪枝。我太弱了。

剪枝的思想就是假如某个质因子被除掉之后仍然可能在后来产生贡献,那么得保证当前数不小于它的平方。剪枝这个东西得多练,我已经很久没有写过搜索的题了……

#include<cstdio>
#include<algorithm>
//#define zczc
using namespace std;
const int N=100010;
inline void read(int &wh){
    wh=0;int f=1;char w=getchar();
    while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
    while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
    wh*=f;return;
}

bool s[N];
int cnt,p[N>>2],v[N];
void pre(){
	for(int i=2;i<N;i++){
		if(s[i])continue;
		p[++cnt]=i;
		for(int j=i+i;j<N;j+=i)s[j]=true;
	}
}

int top,sr,an[N];
inline bool check(int wh){
	if(wh<2)return false;
	for(int i=2;i*i<=wh;i++){
		if(wh%i==0)return false; 
	}
	return true;
}
void dfs(int wh,int num,int nan){
	if(wh==1){an[++top]=nan;return;}
	if(wh<p[num])return;
	if(wh>p[num]&&check(wh-1))an[++top]=nan*(wh-1);
	if(num>cnt)return;
	for(int i=num;p[i]*p[i]<=wh;i++){
		int a=1,b=p[i];
		while((a=a+b)<=wh){
			if(wh%a==0)dfs(wh/a,i+1,nan*b);
			b*=p[i];
		}
	}
}

signed main(){
	
	#ifdef zczc
	freopen("in.txt","r",stdin);
	#endif
	
	pre();
	int m;
	while(~scanf("%d",&m)){
		top=0;
		dfs(m,1,1);
		printf("%d\n",top);
		if(!top)continue;
		sort(an+1,an+top+1);
		for(int i=1;i<=top;i++)printf("%d ",an[i]);
		printf("\n");
	}
	
	return 0;
}
posted @ 2022-05-06 22:20  Feyn618  阅读(10)  评论(0编辑  收藏  举报