![bzoj千题计划297:bzoj3629: [JLOI2014]聪明的燕姿 bzoj千题计划297:bzoj3629: [JLOI2014]聪明的燕姿](https://image.shishitao.com:8440/aHR0cHM6Ly9ia3FzaW1nLmlrYWZhbi5jb20vdXBsb2FkL2NoYXRncHQtcy5wbmc%2FIQ%3D%3D.png?!?w=700&webp=1)
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+],cnt;
bool vis[N+]; int ans[N],tot; void pre()
{
vis[]=true;
for(int i=;i<=N;++i)
{
if(!vis[i]) prime[++cnt]=i;
for(int j=;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=;prime[i]*prime[i]<=x;++i)
if(!(x%prime[i])) return false;
return true;
} void dfs(int last,int num,int rest)
{
if(rest==) { ans[++tot]=num; return; }
if(rest->prime[last] && isprime(rest-)) ans[++tot]=num*(rest-);
for(int i=last+;prime[i]*prime[i]<=rest;++i)
for(int sum=prime[i]+,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=;
dfs(,,n);
sort(ans+,ans+tot+);
printf("%d\n",tot);
for(int i=;i<=tot;++i) printf("%d ",ans[i]);
if(tot) printf("\n");
}
}