题目解析
两个公式:
整数唯一分解定理:
(n=prod_{i=1}^mp_i^{α_i})
约数和定理:
(S=prod_{i=1}^msum_{j=0}^{α_i}p_i^j)
然后可以搜索质因子和它们的指数,记录下当前还剩多少和(s),已经枚举到的第(i)个质数,目前产生的答案(x)。
需要剪枝:若(p^2>=S),有(frac{s}{p+1}<p),而我们又是递增枚举这个(p)的,所以后面就不用枚举了,这个一定不合法(那么所提到的这个答案在(frac{s}{p+1})就已经算过了(因为从小到大))
除非它是最后一个,后面没有数,也就是(p+1==s),那么这种情况可以特判:
如果(s-1)是质数,并且比上一次枚举到的质因子大,那么就把((s-1) imes x)也算入答案。
这道题输出调了我好久(见注释,果然是太菜了嘛(qwq)
虽然我没有燕姿那么聪明,但是希望我也能找到自己等的人叭,不需要所有,有就够了。
►Code View
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
#define LL long long
#define N 100005
#define INF 0x3f3f3f3f
int rd()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48); c=getchar();}
return f*x;
}
int prim[N],pn;
bool vis[N];
int ans[N],cnt;
void Sieve()
{
for(int i=2;i<N;i++)
{
if(!vis[i]) prim[++pn]=i;
for(int j=1;j<=pn&&prim[j]*i<N;j++)
{
vis[i*prim[j]]=1;
if(i%prim[j]==0) break;
}
}
}
bool check(int x)
{
if(x==1) return 0;
for(int i=1;prim[i]*prim[i]<=x;i++)
if(x%prim[i]==0) return 0;
return 1;
}
void dfs(int now,int i,int x)
{//还剩多少没有分解 第几个质数 当前答案
if(now==1)
{
ans[++cnt]=x;
return ;
}
if(check(now-1)&&now-1>prim[i]) ans[++cnt]=(now-1)*x;//sum-1是满足条件的一个质因子
for(int j=i+1;prim[j]*prim[j]<=now;j++)
{//枚举质因子
int sum=1+prim[j],lst=prim[j];
while(sum<=now)
{
if(now%sum==0) dfs(now/sum,j,x*lst);
lst*=prim[j],sum+=lst;
}
}
}
int main()
{
Sieve();
int s;
while(scanf("%d",&s)!=EOF)
{
cnt=0;
dfs(s,0,1);
sort(ans+1,ans+cnt+1);
printf("%d
",cnt);
for(int i=1;i<=cnt;i++)
printf("%d ",ans[i]);
if(cnt) puts("");//Cao 注意格式啊 如果没有数 那么就没有这个换行 也不能这么打(见下
/*
for(int i=1;i<cnt;i++)
printf("%d ",ans[i]);
printf("%d
,ans[cnt]);
因为不知道cnt有没有 如果cnt==0 就会多输出一个ans[0]啊
*/
}
return 0;
}