CF448E 【Divisors】题解--zhengjun
一道函数递归题
记录一下当前的是第几层和现在要分的数是几(分别用 \(x\) 和 \(y\) 表示)
然后,每一次从小到大枚举因子,继续递归直到输出的总数到达 \(10^5\)。
#include<cstdio>
#include<cmath>
#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\) 了。
我们考虑优化:
-
如果当前的数 \(y\) 是 \(1\),那么就不用搜索下去了,直接输出 \(1\)
-
可以先预处理出 \(X\) 的所有因数存在数组 \(p\) 中,那么 \(X\) 的因数的因数 \(\cdots\) 的因数一定是在 \(p\) 中
-
枚举每一个 \(X\) 的因数的时候,如果这个因数已经大于 \(y\) 了,就不用再枚举了(后面的一定比前面的大啊)
最终 AC 代码
#include<cstdio>
#include<cmath>
#include<algorithm>
#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;
}