山东济南彤昌机械科技有限公司 山东济南江鹏工贸游有限公司

bzoj 3629 [JLOI2014]聪明的燕姿(约数和,搜索)

 

【题目链接】

 

  http://www.lydsy.com/JudgeOnline/problem.php?id=3629

 

【题意】

 

  给定S,找出所有约数和为S的数。

 

【思路】

 

  若n=p1^a1*p2^a2*...*pk^ak

  则约数和f(n)为(p1^0+p1+p1^2+...+p1^a1)*(p2^0+p2+p2^2+...+p2^a2)*...*(pk^0+pk+pk^2+...+pk^ak)

  考虑搜索,使得和为S。至于这个搜索怎么写的,我能说我看不懂吗=_=

 

【代码】

 

 1 #include<cmath>
 2 #include<cstdio>
 3 #include<cstring> 
 4 #include<algorithm>
 5 using namespace std;
 6 
 7 typedef long long ll;
 8 const int N = 1e5+100;
 9 
10 ll su[N],vis[N]; ll ans[N];
11 
12 void get_prime()
13 {
14     vis[1]=1;
15     for(int i=2;i<N;i++) {
16         if(!vis[i]) su[++su[0]]=i;
17         for(int j=1;j<=su[0]&&su[j]*i<N;j++) {
18             vis[i*su[j]]=1;
19             if(i%su[j]==0) break;
20         }
21     }
22 }
23 
24 bool is_prime(ll x)
25 {
26     if(x<N) return !vis[x];
27     for(ll i=1;su[i]*su[i]<=x;i++)
28         if(x%su[i]==0) return 0;
29     return 1;
30 }
31 
32 void dfs(ll now,int pos,ll left)
33 {
34     if(left==1) {
35         ans[++ans[0]]=now;
36         return ;
37     }
38     if( left-1>=su[pos] && is_prime(left-1) )
39         ans[++ans[0]]=(left-1)*now;
40     for(int i=pos; su[i]*su[i]<=left ;i++) {
41         ll sum=su[i]+1,pow=su[i];
42         for(;sum<=left;pow*=su[i],sum+=pow)
43             if(left%sum==0)
44                 dfs(now*pow,i+1,left/sum);
45     }
46 }
47 
48 ll S;
49 
50 int main()
51 {
52     get_prime();
53     while(scanf("%lld",&S)!=EOF) {
54         ans[0]=0;
55         dfs(1,1,S);
56         sort(ans+1,ans+ans[0]+1);
57         printf("%d\n",ans[0]);
58         for(int i=1;i<=ans[0];i++)
59             printf("%lld%c",ans[i],i==ans[0]?'\n':' ');
60     }
61     return 0;
62 }

 

posted on 2016-03-30 19:05  hahalidaxin  阅读(524)  评论(0编辑  收藏  举报