题解 CF448E 【Divisors】

一道函数递归题

记录一下当前的是第几层和现在要分的数是几(分别用 x x x y y y 表示)

然后,每一次从小到大枚举因子,继续递归直到输出的总数到达 1 0 5 10^5 105

#include
#include
#define ll long long
using namespace std;
ll a,b,tot;
void dfs(ll x,ll y){
	if(tot>=100000)return;
	if(!x){
		printf("%lld ",y);
		tot++;
		return;
	}
	for(ll i=1;i*i<=y;i++){
		if(y%i)continue;
		dfs(x-1,i);
		if(tot>=100000)return;
	}
	ll k=(ll)(sqrt(y));
	for(ll i=(k*k==y?k-1:k);i>=1;i--){//注意如果这个数是个完全平方数,那么就不能让 sqrt(y) 搜索两次
		if(y%i)continue;
		dfs(x-1,y/i);
		if(tot>=100000)return;
	}
}
int main(){
	scanf("%lld%lld",&a,&b);
	dfs(b,a);
	return 0;
}

然后,你就会发现你稳稳地 T T T 了。

我们考虑优化:

  • 如果当前的数 y y y 1 1 1,那么就不用搜索下去了,直接输出 1 1 1

  • 可以先预处理出 X X X 的所有因数存在数组 p p p 中,那么 X X X 的因数的因数 ⋯ \cdots 的因数一定是在 p p p

  • 枚举每一个 X X X 的因数的时候,如果这个因数已经大于 y y y 了,就不用再枚举了(后面的一定比前面的大啊)

最终 AC 代码

#include
#include
#include
#define ll long long
using namespace std;
ll a,b,tot,p[100001];
void dfs(ll x,ll y){
	if(tot>=100000)return;
	if(!x||y==1){
		printf("%lld ",y);
		tot++;
		return;
	}
	for(ll i=1;i<=p[0]&&p[i]<=y;i++){
		if(y%p[i])continue;
		dfs(x-1,p[i]);
		if(tot>=100000)return;
	}
}
int main(){
	scanf("%lld%lld",&a,&b);
	for(ll i=1;i*i<=a;i++){
		if(a%i==0){
			p[++p[0]]=i;
			if(i*i!=a)p[++p[0]]=a/i;
		}
	}
	sort(p+1,p+1+p[0]);
	dfs(b,a);
	return 0;
}

你可能感兴趣的:(题解 CF448E 【Divisors】)