您的位置:首页 > 其它

2017.9.11 聪明的燕姿 失败总结

2017-09-11 10:27 211 查看
这题有毒、如假包换的爆搜

只要知道一个数的约数加起来=分解质因数后每个  质因数1~pi次前缀和  相乘的结果 就好 做(sou)了

所以如果知道约数和,就可以枚举质因数来爆搜

必须剪枝到极致才能过,不然会T

由于约数和==一堆数的乘积,所以有一个剪枝是只有能整除才去搜

由于分解的质因数不能重,所以递归剩下部分时不能用上一次用的质因数。(去重优化)

由于有可能出现剩下的大于根n,所以及时判断 剩下的数-1 是不是质数 (第一遍写的时候以为剩下的数-1只有一个、、结果狂wa)

然后就可以过了

码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define ll long long
int N,su[1000006],tot,n,ans,daan[1000006];
bool he[1000006];
void eular()
{
int i,j;
for(i=2;i<=N;i++)
{
if(!he[i])
{
su[++tot]=i;
}
for(j=1;j<=tot&&i*su[j]<=N;j++)
{
he[i*su[j]]=1;
if(i%su[j]==0)break;
}
}
}
void dfs(int qi,int o,int ys)
{
int i;ll he,lin;
if(ys==1)
{
daan[++ans]=o;
}
if(ys-1>=su[qi])
{
bool ss=1;
for(i=1;su[i]*su[i]<=ys-1&&i<=tot;i++)
{
if((ys-1)%su[i]==0)ss=0;
}
if(ss)daan[++ans]=o*(ys-1);
}
for (i=qi; su[i]*su[i]<=ys; i++)
for (ll he=1+su[i],lin=su[i]; he<=ys; lin*=(ll)su[i],he+=lin)
if (!(ys%he)) dfs(i+1,o*lin,ys/he);
}
int main()
{
N=sqrt(3000000009);
eular();
int i;
while(~scanf("%d",&n))
{
ans=0;
dfs(1,1,n);
if(ans==0)
{
printf("0\n");
continue;
}
printf("%d\n",ans);
sort(daan+1,daan+1+ans);
for(i=1;i<ans;i++)
printf("%d ",daan[i]);
printf("%d\n",daan[ans]);
// printf("\n");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: