[JLOI2014]聪明的燕姿
搬运自zmy;
题目来源:
http://www.lydsy.com/JudgeOnline/problem.php?id=3629
题目大意:求小于n的升序数字序列 满足它的约数之和等于n
提示:
暴力枚举。
如何求约数之和?
把一个数字用素数分解到最简单的形式后 找到每个数出现的因子次数 相加 再相乘就是答案
恩举个例子: 15=3x5 那么sum=(1+3)*(1+5) = 24;
24=2x2x2x3 那么sum=(1+2+4+8)*(1+3)= 60;
然后dfs咯
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define LL long long
using namespace std;
bool p[1000050]={0};
int prime[1000050],primx=0;
int limt;
int ANS[111111],ans=0;
void getpr(int N){
int m=(int)sqrt(N+0.5);
primx=1;
memset(p,0,sizeof(p));
for(int i=2;i<=m;i++)
{
if(!p[i])
for(int j=i*i;j<=N;j+=i)p[j]=true;
}
for(int i=2;i<=N;i++)
{
if(!p[i])prime[primx++]=i;
}
primx--;
//for(int i=1;i<=45;i++)cout<<prime[i]<<" ";
}
bool isprime(int x)
{
if (x<=100000) return (!p[x]);
int d=sqrt(x);
for (int i=2;i<=d;i++)
if (x%i==0) return false;
return true;
}
void DFS(int pre,int n,int num)
{
if(n==1)
{
ans++;
ANS[ans]=num;
return;
}
if( n-1 > limt && isprime(n-1))//limt是sqrt(N)
{
ans++;
ANS[ans] = num*(n-1);
}
for(int i= pre+1 ; prime[i]<= limt; i++)
{
int sum=1, t=prime[i];
for(int k=1;sum+t<=n;k++)
{
sum+=t; //计算累积和
if(n%sum==0)DFS(i,n/sum,num*t);
t*=prime[i]; //重复一次乘一次
}
}
}
int main()
{
int a,b,c;
int N,M,K;
primx=0;
getpr(100000);
while(scanf("%d",&N)!=EOF)
{
ans=0;
limt=sqrt(N);
DFS(0,N,1);
sort(ANS+1,ANS+ans+1);
cout<<ans<<endl;
for (int i=1;i<=ans;i++)
{
printf("%d",ANS[i]);
if(i!=ans) printf(" ");else printf("\n");
}
}
return 0;
}