题目大意:令f(x)=Σi (i|x) 给定n,求所有的x,使f(x)=n
这题就是今年省选第二题,我没看到多组数据爆零了,不然妥妥30分。。。
首先约数和公式
令n=p1^a1*p2^a2*...*pk^ak
则f(n)=(1+p1+p1^2+...+p1^a1)*(1+p2+p2^2+...+p2^a2)*...*(1+pk+pk^2+...+pk^ak)
于是我们枚举质数p,采取DFS的方式求出所有值
记住DFS时无论什么操作都要O(√n),O(n)必死,O(n/logn)必死,包括枚举质数的时候要用O(√left)的,O(√n)都是死 其中left是n/当前数字的约数和
BZOJ是算总时间的 所以很多人都水过去了 第十个点全都是反质数 O(√n)必死 学校的大神还出了个第十一个点 能把O(√n)卡出14秒 O(√left)秒过
此外枚举质数时别出现重复 这题有的OJ在答案为零的时候要输出一个空行 BZOJ不用打
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 100100
using namespace std;
typedef long long ll;
ll n,p[M],ans[M],tot;
bool not_prime[M];
void Get_Prime()
{
int i,j;
for(i=2;i<=100000;i++)
{
if(!not_prime[i])
p[++p[0]]=i;
for(j=1;p[j]*i<=100000&&j<=p[0];j++)
{
not_prime[p[j]*i]=1;
if(i%p[j]==0)
break;
}
}
}
bool Judge_Prime(ll x)
{
ll i;
if(x==1)
return 0;
for(i=1;p[i]*p[i]<=x;i++)
if(x%p[i]==0)
return 0;
return 1;
}
void DFS(ll now,int pos,ll left)
{
int i;
if(left==1)
{
ans[++ans[0]]=now;
return ;
}
if( left-1>=p[pos] && Judge_Prime(left-1) )
ans[++ans[0]]=(left-1)*now;
for(i=pos; p[i]*p[i]<=left ;i++)
{
ll power_sum=p[i]+1,power=p[i];
for(;power_sum<=left;power*=p[i],power_sum+=power)
if(left%power_sum==0)
DFS(now*power,i+1,left/power_sum);
}
}
int main()
{
int i;
//freopen("swallow.in","r",stdin);
//freopen("swallow.out","w",stdout);
Get_Prime();
while(~scanf("%lld",&n) )
{
ans[0]=0;tot=0;
DFS(1,1,n);
sort(ans+1,ans+ans[0]+1);
cout<<ans[0]<<endl;
for(i=1;i<=ans[0];i++)
printf("%lld%c",ans[i],i==ans[0]?'\n':' ');
//if(!ans[0])
// cout<<endl;
}
}
对比一下最后一个点
void DFS(ll now,int pos,ll left)
{
int i;
if(left==1)
{
ans[++ans[0]]=now;
return ;
}
if( (left-1)*(left-1)>=n && Judge_Prime(left-1) )
ans[++ans[0]]=(left-1)*now;
for(i=pos;p[i]<=left&&p[i]*p[i]<=n;i++)
{
ll power_sum=p[i]+1,power=p[i];
for(;power_sum<=left;power*=p[i],power_sum+=power)
if(left%power_sum==0)
DFS(now*power,i+1,left/power_sum);
}
}
O( min(√n,left) ) 14s出解
void DFS(ll now,int pos,ll left)
{
int i;
if(left==1)
{
ans[++ans[0]]=now;
return ;
}
if( (left-1)*(left-1)>=n && Judge_Prime(left-1) )
ans[++ans[0]]=(left-1)*now;
for(i=pos;p[i]*p[i]<=n;i++)
{
ll power_sum=p[i]+1,power=p[i];
for(;power_sum<=left;power*=p[i],power_sum+=power)
if(left%power_sum==0)
DFS(now*power,i+1,left/power_sum);
}
}
O(√n) 被卡了整整100s都没出解