题目描述
题解
有一个计算
n=∏ipkii
约数和的公式
d(i)=∏i(∑j=0kipji)
然后对求和部分用一下等比数列求和公式可以得到
d(i)=∏ipki+1i−1pi−1
那么可以考虑爆搜s的所有小于
s√
的所有质因子以及次数,然后计算最后一个大质因子,然后通过这些质因子计算答案
注意爆搜的过程中有一些重要的剪枝,比如说判断是非能整除等等
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define N 50005
int s;
int p[N],prime[N],ans[N];
void get(int n)
{
for (int i=2;i<=n;++i)
{
if (!p[i]) prime[++prime[0]]=i;
for (int j=1;j<=prime[0]&&i*prime[j]<=n;++j)
{
p[i*prime[j]]=1;
if (i%prime[j]==0) break;
}
}
}
void check(int now,int nowans)
{
int pnow=now-1;
if (pnow<sqrt(s)) return;
for (int i=2;i*i<=pnow;++i)
if (pnow%i==0) return;
ans[++ans[0]]=nowans*pnow;
}
void dfs(int now,int nowans,int last)
{
check(now,nowans);
if (now==1)
{
ans[++ans[0]]=nowans;
return;
}
for (int i=last+1;i<=prime[0];++i)
{
int mul=1;
for (int j=1;;++j)
{
if (mul>now/prime[i]) break;
mul*=prime[i];
long long sum=((long long)mul*prime[i]-1)/(prime[i]-1);
if (sum>now) break;
if (now%(int)sum) continue;
dfs(now/(int)sum,nowans*mul,i);
}
}
}
int main()
{
get(50000);
while (~scanf("%d",&s))
{
ans[0]=0;
dfs(s,1,0);
sort(ans+1,ans+ans[0]+1);
ans[0]=unique(ans+1,ans+ans[0]+1)-ans-1;
printf("%d\n",ans[0]);
for (int i=1;i<=ans[0];++i)
printf("%d%c",ans[i]," \n"[i==ans[0]]);
}
return 0;
}