http://acm.hdu.edu.cn/showproblem.php?pid=4282
对于方程X^Z + Y^Z + XYZ = K,已知K求此方程解的个数,其中要求X<Y,Z>1,而K的范围是0到2^31。
首先我们来分析Z的范围:由于X,Y为正整数,X < Y,则1 < X < Y, =====> Y >= 2
=> X^Z + Y^Z + XYZ > Y^Z
=> 2^Z <= Y^Z < 2^31
所以得到2 <= Z<31
对于Z=2时式子左边可以化为(x+y)^2 = k 的形式。
所以当k 是完全平方数的时候,(x,y) 才有可能有解。
假如m^2 = k ,问题就相当于求x+y = m (x < y) 的解的组数。
容易得出ans=(m-1)/2。
而Z在3<=Z<31的情况。
我们再来分析X的范围:
对于方程X^Z + Y^Z + XYZ = K, X < Y,则有X^Z + Y^Z + XYZ > 2*X^Z + X*X*Z >= 2*X^3 + 3*X^2
即我们得到:2*X^3 + 3*X^2 < 2^31 解这个方程有:X < 1024
于是现在我们得到了3 <= Z < 31,1 <= X < 1024,当然Z=2特殊处理。接下来就直接枚举X,Z,再枚举Y。
复杂度O(10^4)左右,因为y不会和相差太远
#pragma comment(linker, "/STACK:36777216") #pragma GCC optimize ("O2") #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <string> #include <queue> #include <map> #include <iostream> #include <algorithm> using namespace std; #define RD(x) scanf("%I64d",&x) #define RD2(x,y) scanf("%d%d",&x,&y) #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define clr0(x) memset(x,0,sizeof(x)) #define eps 1e-9 const double pi = acos(-1.0); typedef long long LL; typedef unsigned long long ULL; const int modo = 1e9 + 7; const int INF = 0x3f3f3f3f; const int maxn = 1005,N = 50000; LL s,k,ans; LL f[1300][32]; void init() { for(int i = 1; i < 1300;++i){ f[i][0] = 1; for(int j = 1;j < 32;++j){ f[i][j] = f[i][j-1]*i; if(f[i][j] > (1LL<<31)) break; } } } int main(){ init(); while(~RD(k),k){ ans = 0; s = sqrt(k); if(s * s == k){ ans += (s - 1)/ 2; } for(int x = 1;x < 1024;++x){ for(int z = 3;z < 31;++z){ if(f[x][z] == 0) break; for(int y = x + 1;;++y){ if(f[y][z] == 0 || f[x][z] + f[y][z] + x*y*z > k) break; else if(f[x][z] + f[y][z] + x*y*z == k){ ans ++ ; break; } } } } printf("%I64d ",ans); } return 0; }