题目连接: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多)