BZOJ 3629[JLOI2014]聪明的燕姿
3629: [JLOI2014]聪明的燕姿
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1386 Solved: 507
[Submit][Status][Discuss]
Description
阴天傍晚车窗外
未来有一个人在等待
向左向右向前看
爱要拐几个弯才来
我遇见谁会有怎样的对白
我等的人他在多远的未来
我听见风来自地铁和人海
我排着队拿着爱的号码牌
城市中人们总是拿着号码牌,不停寻找,不断匹配,可是谁也不知道自己等的那个人是谁。可是燕姿不一样,燕姿知道自己等的人是谁,因为燕姿数学学得好!燕姿发现了一个神奇的算法:假设自己的号码牌上写着数字S,那么自己等的人手上的号码牌数字的所有正约数之和必定等于S。
所以燕姿总是拿着号码牌在地铁和人海找数字(喂!这样真的靠谱吗)可是她忙着唱《绿光》,想拜托你写一个程序能够快速地找到所有自己等的人。
Input
输入包含k组数据(k<=100)对于每组数据,输入包含一个号码牌S
Output
对于每组数据,输出有两行,第一行包含一个整数m,表示有m个等的人,第二行包含相应的m个数,表示所有等的人的号码牌。注意:你输出的号码牌必须按照升序排列。
Sample Input
42
Sample Output
3
20 26 41
20 26 41
HINT
对于100%的数据,有S<=2*10*9
由唯一分解定理:
ans=p1^k1*p2^k2……pn^kn
n=(1+p1+……+p1^k1)*(1+p2+……+p2^k2)*……*(1+pn+……+pn^kn)
可以深搜枚举质数,判断是否是n的因子。
注意特判。
1 #include<iostream> 2 #include<stdio.h> 3 #include<math.h> 4 #include<algorithm> 5 using namespace std; 6 #define maxn 100000 7 #define LL long long 8 int p[maxn+1],cnt; 9 bool book[maxn+1]; 10 int t,num; 11 int ans[200001]; 12 void init() 13 { 14 for(int i=2;i<=maxn;i++) 15 { 16 if(!book[i]) 17 p[++cnt]=i; 18 for(int j=1;j<=cnt&&p[j]*i<=maxn;j++) 19 { 20 book[i*p[j]]=true; 21 if((i%p[j])==0) 22 break; 23 } 24 } 25 } 26 bool judge(int x) 27 { 28 if(x==1) 29 return false; 30 if(x<=maxn) 31 return !book[x]; 32 for(int i=1;p[i]*p[i]<=x;i++) 33 if(x%p[i]==0) 34 return false; 35 return true; 36 } 37 void dfs(LL s,int pos,LL x) 38 { 39 if(s==1) 40 { 41 ans[++num]=x; 42 return ; 43 } 44 if(judge(s-1)&&s-1>=p[pos]) 45 ans[++num]=x*(s-1); 46 LL sum,indx; 47 for(int i=pos;p[i]*p[i]<=s;i++) 48 { 49 sum=p[i]+1; 50 indx=p[i]; 51 for(;sum<=s;indx*=p[i],sum+=indx) 52 if(s%sum==0) 53 dfs(s/sum,i+1,x*indx); 54 } 55 } 56 int n; 57 int main() 58 { 59 init(); 60 while(scanf("%d",&n)!=EOF) 61 { 62 dfs(n,1,1); 63 printf("%d\n",num); 64 if(num) 65 { 66 sort(ans+1,ans+num+1); 67 for(int i=1;i<=num;i++) 68 printf("%d%c",ans[i],i==num?'\n':' '); 69 num=0; 70 } 71 } 72 }
(PS:BZOJ卡输出空格,miller_rabin判断不是TLE就是WA)