写完这道题感觉人生都是灰暗的。。。
不存在的!!!数学学得好就知道自己等的人是谁?
这是不不不不不可能的!!!我到现在都没有女朋友!!!
题意
阴天傍晚车窗外
未来有一个人在等待
向左向右向前看
爱要拐几个弯才来
我遇见谁会有怎样的对白
我等的人他在多远的未来
我听见风来自地铁和人海
我排着队拿着爱的号码牌
城市中人们总是拿着号码牌,不停寻找,不断匹配,可是谁也不知道自己等的那个人是谁。可是燕姿不一样,燕姿知道自己等的人是谁,因为燕姿数学学得好!燕姿发现了一个神奇的算法:假设自己的号码牌上写着数字S,那么自己等的人手上的号码牌数字的所有正约数之和必定等于S。
所以燕姿总是拿着号码牌在地铁和人海找数字(喂!这样真的靠谱吗)可是她忙着唱《绿光》,想拜托你写一个程序能够快速地找到所有自己等的人。
Input
输入包含k组数据(k<=100)对于每组数据,输入包含一个号码牌S
Output
对于每组数据,输出有两行,第一行包含一个整数m,表示有m个等的人,第二行包含相应的m个数,表示所有等的人的号码牌。注意:你输出的号码牌必须按照升序排列。
Solution
这道题异常明显考到了约数和定理。。。
完全搞不清省选题怎么会考小学奥数。。。
证明一下:
已知一个正整数n,就可以得到n=(p1^k1)*(p2^k2*)*......*(pm^km);
其中pi(1<=i<=m)是质数,也就是n的质因数。。。
将每一个(pi^ki)分成若干个不同因数:(pi^0),(pi^1),.....,(pi^ki);
于是得到n因数的个数f[n]=(1+k1)*(1+k2)*......*(1+km);
而n所有因数和h[n]=(1+p1^1+p1^2+...+p1^k1)*(1+p2^1+p2^2+...+p2^k2)*....*(1+pm^1+pm^2+...+pm^km);
知道这个定理后,只要深搜就能很容易做出这道题。。。
注意题目中s范围很大,一定要剪枝。。。
代码
#include<cstdio> #include<iostream> #include<algorithm> #define LL long long #define M 100100 using namespace std; LL n,p[M],ans[M],tot; bool not_pri[M]; void get_pri(){ int i,j; for(i=2;i<=100000;i++){ if(!not_pri[i]) p[++p[0]]=i; for(j=1;p[j]*i<=100000&&j<=p[0];j++){ not_pri[p[j]*i]=1; if(i%p[j]==0) break; } } } bool judge_pri(LL x){ LL i; if(x==1) return 0; for(i=1;p[i]*p[i]<=x;i++) if(x%p[i]==0) return 0; return 1; } void dfs(LL now,int pos,LL left){ int i; if(left==1){ ans[++ans[0]]=now; return; } if(left-1>=p[pos]&&judge_pri(left-1)) ans[++ans[0]]=(left-1)*now; for(i=pos;p[i]*p[i]<=left;i++){ LL power_sum=p[i]+1; LL power=p[i]; for(;power_sum<=left;power*=p[i],power_sum+=power) if(left%power_sum==0) dfs(now*power,i+1,left/power_sum); } } int main(){ int i; get_pri(); while(scanf("%lld",&n)==1){ ans[0]=0; tot=0; dfs(1,1,n); sort(ans+1,ans+ans[0]+1); printf("%lld\n",ans[0]); for(i=1;i<=ans[0];i++) printf("%lld%c",ans[i],i==ans[0]?‘\n‘:‘ ‘); } return 0; }
This passage is made by Yukino.