题目大意
给出一个数 x x x,问能否找到唯一的 i , j , k i,j,k i,j,k使得 i 3 + j 3 + k 3 = x i^3+j^3+k^3=x i3+j3+k3=x,否则输出 i n p o s s i b l e inpossible inpossible。
解题思路
题目 x x x的范围只有 0 − 200 0-200 0−200,显然是打表的。但打表的效率决定了出题的速度,先写一个二重循环,接下来二分查找第三个数。另外鉴于 [ − 5000 , 5000 ] [-5000,5000] [−5000,5000]内的立方数需要重复计算,可以用哈希 m a p map map存起来,然后我们只要查值即可。另外还可以优化的是, i 3 + j 3 + k 3 = x i^3+j^3+k^3=x i3+j3+k3=x,这里 x ≥ 0 x≥0 x≥0,显然 i , j , k i,j,k i,j,k至少有一个大于等于0,这就又优化了一半的区间。
代码一:(6616s)
#include <iostream>
#include<tr1/unordered_map>
using namespace std;
typedef long long ll;
tr1::unordered_map<int,ll> mp;
ll mid;
bool b_search(ll x) {
ll l=0,r=5000;
while(r-l>=0) {
mid=(l+r)>>1;
ll res=mp[mid];
if(res==x)
return true;
if(res>x) r=mid-1;
else l=mid+1;
}
return false;
}
bool solve(int x) {
for (ll i=-5000;i<=5000;i++) {
for (ll j=-5000;j<=5000;j++) {
ll ans=x-mp[i]-mp[j];
if(b_search(ans)){
printf("a[%d] = %lld;\n",x,i);
printf("b[%d] = %lld;\n",x,j);
printf("c[%d] = %lld;\n",x,mid);
return true;
}
}
}
return false;
}
int main() {
freopen("ans.txt","w",stdout);
for(ll i=-5000;i<=5000;i++)
mp[i]=i*i*i;
for(int x=0;x<=200;x++){
if (solve(x)){
printf("vis[%d] = true;\n",x);
}
else
printf("vis[%d] = false;\n",x);
}
return 0;
}
可上面的方法还是很慢,不理想,需要再次优化,显然 i , j , k i,j,k i,j,k只有两种情况,即两正一负或者两负一正,我们只枚举两正一负的情况,因为两正一负和两负一正一定是只对每个数取相反数,那么只需枚举 i ∈ [ 0 , 5000 ] , j ∈ [ 0 , 5000 ] i \in [0,5000],j \in [0,5000] i∈[0,5000],j∈[0,5000],然后从 [ − 5000 , 5000 ] [-5000,5000] [−5000,5000]寻找 k k k。
打表代码二:(138s)
#include<bits/stdc++.h>
#include<tr1/unordered_map>
using namespace std;
typedef long long ll;
tr1::unordered_map<ll,int> f;
ll g(ll x){
for(ll i=-5000;i<=5000;i++)
if (i*i*i==x) return i;
}
bool find(int x){
for(ll i =0;i<=5000;i++)
for(long long j=0;j<=5000;j++)
if (f.count(i*i*i+j*j*j+x)){
printf("a[%d] = %lld;\n",x,g(i*i*i+j*j*j+x));
printf("b[%d] = %lld;\n",x,-i);
printf("c[%d] = %lld;\n",x,-j);
return true;
}else if (f.count(i*i*i+j*j*j-x)){
//printf("%lld %lld %lld = %d\n",i,j,-g(i*i*i+j*j*j-x),x);
printf("a[%d] = %lld;\n",x,g(i*i*i+j*j*j-x)==0?0:-g(i*i*i+j*j*j-x));
printf("b[%d] = %lld;\n",x,i);
printf("c[%d] = %lld;\n",x,j);
return true;
}
return false;
}
int main()
{
freopen("ans.txt","w",stdout);
f.clear();
for(ll i=-5000;i<=5000;i++)
f[i*i*i] = 1;
for(int x=0;x<=200;x++){
//printf("find %d\n",x );
if (find(x)){
printf("vis[%d] = true;\n",x);
}
else
printf("vis[%d] = false;\n",x);
}
return 0;
}
提交代码:
#include <iostream>
using namespace std;
int a[201],b[201],c[201];
bool vis[201];
void init(){
///打表出来的东西复制过来即可
}
int main(){
int T,x;
init();
cin>>T;
while(T--){
cin>>x;
if(vis[x]) printf("%d %d %d\n",a[x],b[x],c[x]);
else printf("impossible\n");
}
return 0;
}