bzoj千题计划297:bzoj3629: [JLOI2014]聪明的燕姿
http://www.lydsy.com/JudgeOnline/problem.php?id=3629
约数和定理:
若n的标准分解式为 p1^k1 * p2^k2 ……
那么n的约数和= π (Σ pi^xi ) xi∈[0,ki]
原本枚举小于S的质数,通过先判断S-1是不是质数 就可以 枚举根号S内的质数
#include<cstdio> #include<algorithm> using namespace std; #define N 1000000 int prime[N+1],cnt; bool vis[N+1]; int ans[N],tot; void pre() { vis[1]=true; for(int i=2;i<=N;++i) { if(!vis[i]) prime[++cnt]=i; for(int j=1;j<=cnt;++j) { if(i*prime[j]>N) break; vis[i*prime[j]]=true; if(!(i%prime[j])) break; } } } bool isprime(int x) { if(x<=N) return !vis[x]; for(int i=1;prime[i]*prime[i]<=x;++i) if(!(x%prime[i])) return false; return true; } void dfs(int last,int num,int rest) { if(rest==1) { ans[++tot]=num; return; } if(rest-1>prime[last] && isprime(rest-1)) ans[++tot]=num*(rest-1); for(int i=last+1;prime[i]*prime[i]<=rest;++i) for(int sum=prime[i]+1,nnum=prime[i];sum<=rest;nnum*=prime[i],sum+=nnum) if(!(rest%sum)) dfs(i,num*nnum,rest/sum); } int main() { pre(); int n; while(scanf("%d",&n)!=EOF) { tot=0; dfs(0,1,n); sort(ans+1,ans+tot+1); printf("%d\n",tot); for(int i=1;i<=tot;++i) printf("%d ",ans[i]); if(tot) printf("\n"); } }