我有一个问题,让我们说: 找到所有两对数字(x,y)和(z,t),使x³+y³=z³+t³,其中< strong>(x,y)!=(z,t)和x³+y³&lt;万
取10,000个月的立方根21.544 - &gt;圆到21,所以我得到了:
#include <iostream>
using namespace std;
int main() {
for( int x = 1; x <= 20; ++x ) {
for( int y = x + 1; y <= 21; ++y ) {
for( int z = x + 1; z <= y - 1; ++z ) {
for( int t = z; t <= y - 1; ++t ) {
if( x*x*x + y*y*y == z*z*z + t*t*t ) {
cout << x << ", " << y << ", " << z << ", " << t << endl;
}
}
}
}
}
return 0;
}
我知道这个代码可以进行更多优化,这就是我正在寻找的东西。另外,我的一个朋友告诉我, y 可能是 x + 2 而不是 x + 1 ,我怀疑这是否如果
x = 1 ,那么我们永远不会有 y = 2 ,在这种情况下错过了一个可能的解决方案。
有什么想法吗?
答案 0 :(得分:8)
在给定当前循环结构的情况下,可以进行一种明显的算法优化,通过将范围限制为10,000的立方根,可以非常正确地进行优化。但是,根据10,000 - x的立方根,您可以更进一步限制y的范围。这是你可以做的一件事。
另一个优化是,地球上没有理由认为这应该是4个循环。只需做2个循环并计算x ^ 3 + y ^ 3的值并检查重复。 (这很好,如果你没有深入研究立方根的特征,你会得到的。) 这实际上并没有正确使用API,但您明白了这一点:
multimap<int, std::pair<int, int> > map;
for (int i = 1; i < 21; i++) {
(for int j = x; j < cube_root(10000 - i^3); j++ {
multimap.insert (i^3 + j^3, std::pair<int, int>(i,j);
然后你只需遍历多重图并寻找重复。
答案 1 :(得分:3)
典型权衡:速度记忆。
首先x
上的界限非常大:如果我们假设(x,y)
与x <= y
一起订购,那么
x^3 + y^3 < N and x^3 < y^3 (for positive numbers)
=> x^3 + x^3 < N (by transitivity)
<=> x^3 < N/2
<=> x <= floor((N/2)^(1/3))
因此x <= 17
。
现在,让我们记住x^3 + y^3
的结果并构建一个关联表(sum - &gt;对)。顺便说一句,是否有理由将(x,x)
作为一对丢弃?
int main(int argc, char* argv[])
{
typedef std::pair<unsigned short, unsigned short> Pair;
typedef std::vector<Pair> PairsList;
typedef std::unordered_map<unsigned short, PairsList> SumMap;
// Note: arbitrary limitation, N cannot exceed 2^16 on most architectures
// because of the choice of using an `unsigned short`
unsigned short N = 10000;
if (argc > 1) { N = boost::lexical_cast<unsigned short>(argv[1]); }
SumMap sumMap;
for (unsigned short x = 1; x*x*x <= N/2; ++x)
{
for (unsigned short y = x; x*x*x + y*y*y <= N; ++y)
{
sumMap[x*x*x + y*y*y].push_back(Pair(x,y));
}
}
for (SumMap::const_reference ref: sumMap)
{
if (ref.second.size() > 1)
{
std::cout << "Sum: " << ref.first
<< " can be achieved with " << ref.second << "\n";
// I'll let you overload the print operator for a vector of pairs
}
}
return 0;
}
我们在这里是O(N ^ 2)。
答案 2 :(得分:2)
列出所有数字及其运算结果。按结果对列表进行排序。测试具有不同操作数的匹配结果。
答案 3 :(得分:2)
使用总和表格来生成该总和的数字对。
您可以通过两个嵌套for循环生成该表,然后运行表,使用多个解决方案收集总和。
答案 4 :(得分:2)
我建议计算外循环中的幂(编辑:从for
循环中移出计算):
int x3, y3, z3;
for( int x = 1; x <= 20; ++x ) {
x3 = x * x * x;
for( int y = x + 1; y <= 21; ++y ) {
y3 = y * y * y;
for( int z = x + 1; z <= y - 1; ++z ) {
z3 = z * z * z;
for( int t = z; t <= y - 1; ++t ) {
if( x3 + y3 == z3 + t*t*t ) {
cout << x << ", " << y << ", " << z << ", " << t << endl;
}
}
}
}
}
无论如何,你为什么要优化(至少在这个例子中)?这在我的电脑上运行20毫秒...所以我猜你在更大规模上有类似的问题。
答案 5 :(得分:1)
作为总摘要:
int xcubed = x*x*x;
(与y和z类似)。这可以节省您多次计算相同的值。把它们放在一张表中,这样你只需计算一次。为了测试性能,您当然可以选择更高的maxsum值(以及运行几次)。
算法严格为O(N ^ 2/3)。 (2/3,因为你只去N的立方根,然后在那个较小的范围内是O(m ^ 2)。