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) 编辑 收藏 举报