HDU4282 A very hard mathematic problem(枚举+二分)

题目链接“:

http://acm.hdu.edu.cn/showproblem.php?pid=4282


题意:

给定一个方程式 :    x^z + y^z + x*y*x = k;

对于给定的k,有多少个三元组 (x,y,z) 

使这个方程成立。

其中   0<x<y , z<1 ,k<2^32;

x,y,z,都是正整数。


分析:

现根据题目的范围和方程的结构可以先预测一下每个数的范围。

2<=z<=32 , 1<=x<y<2^16;

然后我们在分析一下方程。发现当,其中任意两个数固定的时候

这个方程的左边都是单调递增的。因此我们可以枚举其中的两个

然后二分判断另外一个存不存在。为了方便 我们可以枚举z,y.

二分判断x.


代码如下:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;

typedef long long LL;

LL k;

LL quick(LL a,LL b)
{
    LL tmp =1;
    for(int i=0;i<b;i++){
        tmp=tmp*a;
        if(tmp>=k) return -1;
    }
    return tmp;
}

LL calu(LL x,LL y,LL z){
    return quick(x,z)+quick(y,z)+x*y*z;
}
bool bin_search(LL y,LL z){
    LL low = 1,high = y,mid;
    while(low<high){
        mid=(low+high)>>1;
        LL tmp = calu(mid,y,z);
        //cout<<"mid "<<mid<<endl;
        //cout<<"tmp "<<tmp<<endl;
        if(tmp==k) return true;
        else if(tmp<k) low=mid+1;
        else high =mid;
    }
    return false;
}

int main()
{
    while(~scanf("%lld",&k)&&k!=0){
        if(k==1||k==2){
            puts("0");
            continue;
        }
        LL INF = (LL) sqrt(k*1.0);
        LL cnt=0;
        for(LL z = 2;z<=32;z++){
            for(LL y = 2;y<=INF;y++){
                LL tmp = quick(y,z);
                if(tmp == -1) break;
                if(bin_search(y,z))
                    cnt++;
            }
        }
        printf("%I64d\n",cnt);
    }
    return 0;
}



你可能感兴趣的:(HDU4282 A very hard mathematic problem(枚举+二分))