您的位置:首页 > 其它

bzoj3629 [JLOI2014]聪明的燕姿(数论+dfs)

2018-03-17 18:12 351 查看
首先我们有约数和公式:

若x=∏i=1npqii

则x的约数和d(x)=∏i=1n∑j=0qipji

于是我们可以枚举质因子pi,爆搜答案。要注意优秀的剪枝技巧qaq

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
inline char gc(){
static char buf[1<<16],*S,*T;
if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(S==T) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
int prime
,tot=0;
ll n,ans
;bool notprime
;
inline void getprime(){
notprime[1]=1;
for(int i=2;i<=100000;++i){
if(!notprime[i]) prime[++tot]=i;
for(int j=1;i*prime[j]<=100000;++j){
notprime[i*prime[j]]=1;
if(i%prime[j]==0) break;
}
}
}
inline bool isprime(ll x){
if(x==1) return 0;
for(int i=1;prime[i]*prime[i]<=x;++i)
if(x%prime[i]==0) return 0;return 1;
}
void dfs(ll res,int pos,ll left){
if(left==1){ans[++ans[0]]=res;return;}
if(left-1>=prime[pos]&&isprime(left-1)) ans[++ans[0]]=res*(left-1);
for(int i=pos;prime[i]*prime[i]<left;++i){//必须平方<left,否则一定不行,剪枝
ll sum=1+prime[i],tmp=prime[i];
for(;sum<=left;tmp*=prime[i],sum+=tmp)
if(left%sum==0) dfs(res*tmp,i+1,left/sum);
}
}
int main(){
//  freopen("a.in","r",stdin);
getprime();
while(~scanf("%lld",&n)){
ans[0]=0;dfs(1,1,n);sort(ans+1,ans+ans[0]+1);
printf("%lld\n",ans[0]);
for(int i=1;i<ans[0];++i) printf("%lld ",ans[i]);
if(ans[0]) printf("%lld\n",ans[ans[0]]);
}return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: