题目连接:ZOJ-3673
题目大意:给出一个数字m,求满足m = a^3 + b^3(a,b为正整数)的所有整数对。
题目思路:
已知 m = a3+b3=(a+b)(a2−a∗b+b2) ①
设 t = a + b; ②
②代入①,因为 m = (a+b)((a+b)2−3∗a∗b)
可得,n = a∗b=(t2−m/t)/3
–> a2+a∗t+n=0 ; 求出a可得b
关键求m的约数即为(a+b)(以上from my son loy)
#include<bits/stdc++.h> #define ll unsigned long long #define maxn 2642246*2 //n=a^3+b^3=(a+b)(a^2-ab+b^2),a和b都不大于3√(2^64)=2642245 using namespace std; struct node{ int a,b; //n所含素因子和个数 }x[maxn+2]; int noprime[maxn+2]; vector<int> isprime; vector<pair<int,int> > ans; ll n; int c; map<int,int> r; void gao(ll t){ //t=a+b if((t*t-n/t)%3!=0) return; ll m=(t*t-n/t)/3; //n=a^3+b^3=(a+b)(a^2-ab+b^2)=(a+b)((a+b)^3-3ab),m=a*b=(t^2-n/t)/3 ll delta=t*t-4*m; //由a+b=t和a*b=m 得出 a^2-t*a+m=0 if(delta<0) return; double a=(t+sqrt(delta))/2.0; if(a>=t) return; //是否有一个≤0 if(a-(ll)a==0&&r[min(a,t-a)]==0){ r[min(a,t-a)]=1; ans.push_back({min(a,t-a),max(a,t-a)}); } } void dfs(int p,ll s){ if(s>1&&s<=maxn) gao(s); if(p>c) return; ll ss=1; for(int i=0;i<=x[p].b;++i){ dfs(p+1,s*ss); ss*=x[p].a; } } int main(){ for(int i=2;i<=maxn;++i){ if(noprime[i]==0){ isprime.push_back(i); for(int j=i*2;j<=maxn;j+=i){ noprime[j]=1; } } } while(~scanf("%llu",&n)){ r.clear(); ans.clear(); ll tmp=n; c=-1; for(int i=0;i<isprime.size();++i){ //这里预处理素数可以防止超时,学习 if(n%isprime[i]==0){ int s=0; while(n%isprime[i]==0){ s++; n/=isprime[i]; } x[++c].a=isprime[i]; x[c].b=s; } if(n==1) break; //这句必须要加,否则超时!!! } if(n>1){ x[++c].a=n; x[c].b=1; } n=tmp; dfs(0,1); sort(ans.begin(),ans.end()); printf("%d",ans.size()); for(int i=0;i<ans.size();i++){ printf(" (%llu,%llu)",ans[i].first,ans[i].second); } printf("\n"); } return 0; }
之所以要分解素因子的原因在于,下面这个代码是会超时的:
#include<bits/stdc++.h> #define ll unsigned long long #define maxn (ll)2642246 //n=a^3+b^3=(a+b)(a^2-ab+b^2),a和b都不大于3√(2^64)=2642245 using namespace std; vector<pair<int,int> > v; map<ll,int> r; int main(){ ll n; while(scanf("%llu",&n)!=EOF){ v.clear(); r.clear(); for(ll t=2;t<=min((ll)pow(n,1.0/3)*2,maxn);++t){ //直接遍历所有t的可能值 if((t*t-n/t)%3!=0) continue; ll m=(t*t-n/t)/3; //n=a^3+b^3=(a+b)(a^2-ab+b^2)=(a+b)((a+b)^3-3ab),m=a*b=(t^2-n/t)/3 ll delta=t*t-4*m; //由a+b=t和a*b=m 得出 a^2-t*a+m=0 if(delta<0) continue; double a=(t+sqrt(delta))/2.0; if(a>=t) continue; //是否有一个≤0 if(a-(ll)a==0&&r[min(a,t-a)]==0){ r[min(a,t-a)]=1; v.push_back({min(a,t-a),max(a,t-a)}); } } sort(v.begin(),v.end()); printf("%d",v.size()); for(int i=0;i<v.size();++i) printf(" (%d,%d)",v[i].first,v[i].second); printf("\n"); } return 0; }其实自己觉得两个复杂度差不多,第一个代码isprime.size()也有3w多,为什么超时我也不知道了。也许是卡在大数据多(一个3w多,一个20w多)