题目大意:令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); } }