bzoj千题计划297:bzoj3629: [JLOI2014]聪明的燕姿

时间:2023-03-09 06:28:37
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+],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");
}
}