我想制作C#程序,用于在给定间隔中找到正整数a,b,c,x,y,z的组合,使得a x x + b ^ y = c ^ z。变量a,b,c必须在区间[abc_min,abc_max]中,x,y,z必须在区间[xyz_min,xyz_max]中。我尝试使用六个for循环,但它非常慢。是否有更好的代码可以在很短的时间内找到非常大的区间(例如[0,100])中的所有组合?这是我的代码,但速度很慢:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Numerics;
namespace ConsoleApplication8
{
class Program
{
static void Main(string[] args)
{
try
{
int abc_min = 3, abc_max = 10, xyz_min = 3, xyz_max = 20, num = 0;
int a, b, c, x, y, z;
BigInteger p1, p2, p3;
for (a = abc_min; a <= abc_max; a++)
{
for (b = abc_min; b <= abc_max; b++)
{
for (c = abc_min; c <= abc_max; c++)
{
for (x = xyz_min; x <= xyz_max; x++)
{
for (y = xyz_min; y <= xyz_max; y++)
{
for (z = xyz_min; z <= xyz_max; z++)
{
p1 = BigInteger.Pow(a, x);
p2 = BigInteger.Pow(b, y);
p3 = BigInteger.Pow(c, z);
if (p1 + p2 == p3)
{
Console.WriteLine("{0}^{1}+{2}^{3}={4}^{5}\n", a, x, b, y, c, z);
num += 1;
Console.ReadKey();
Console.WriteLine("----------------------------\n");
}
}
}
}
}
}
}
Console.WriteLine("{0} instances found.", num);
}
catch
{
Console.WriteLine("\nError occured.");
}
Console.ReadKey();
}
}
}
答案 0 :(得分:0)
这是一个想法..
首先,定义看起来像这样的类(这是所有释义的C#,可能需要重构):
class Exponential
{
public int base;
public int power;
}
class ExponentialResult : List<Exponential>
{
private BigInteger result;
public ExponentialResult(BigInteger value)
{
result = value;
}
public BigInteger Result
{
get { return result; }
}
}
public BigIntegerComparer : IComparer
{
public int Compare(BigIntegerComparer x, BigIntegerComparer y)
{
return (int) BigInteger.Subtract(x, y);
}
}
然后,您希望使用类似以下内容的方式将表单的所有值(base ^ power)累积到Exponential
个对象中
public Dictionary<BigInteger, ExponentialResult> AccumulateRange(int base_min, int base_max, int power_min, int power_max)
{
Dictionary<BigInteger, ExponentialResult> dictionary = new Dictionary<BigInteger, ExponentialResult>();
for (int base = base_min; base <= base_max; ++base)
{
for(int power = power_min; power <= power_max; ++power)
{
Exponential exp = new Exponential();
exp.base = base;
exp.power = power;
BigInteger result = BigInteger.Pow(base, power);
ExponentialResult set;
if (!dictionary.TryGetValue(result, out set))
{
set = new ExponentialResult(result);
dictionary.Add(result, set);
}
set.Add(exp);
}
}
}
一旦你拥有了指定范围内的整个值集,你就会想要对它们进行排序并对它们进行正确迭代,并检查添加内容以及不是:
public void Calculate(IDictionary<BigInteger, ExponentialResult> dictionary)
{
SortedList<BigInteger, ExponentialResult> list = new SortedList<BigInteger, ExponentialResult>(dictionary, new BigIntegerComparer());
foreach (KeyValuePair<BigInteger, ExponentialResult> kv1 in list)
{
foreach (KeyValuePair<BigInteger, ExponentialResult> kv2 in list)
{
ExponentialResult sum;
if (list.TryGetValue(BigInteger.Add(kv1.Key, kv2.Key), out sum))
{
//we have found one such that a^x + b^y = c^z
}
if (kv1 == kv2)
{
break;
}
}
}
}
然后,在评论所在的if
内部,累积一组结果,以便ExponentialResult kv1.Value
中存储的所有对与ExponentialResult kv2.Value
中存储的所有对组合在一起},导致所有对存储在ExponentialResult sum
。
答案 1 :(得分:0)
对于给定的时间间隔,您最初可以计算出a
幂的所有x
值的数组:
BigInteger[,] abcPow = new BigInteger[abc_max - abc_min + 1, xyz_max - xyz_min + 1];
for (a = abc_min; a <= abc_max; a++)
for (x = xyz_min; x <= xyz_max; x++)
abcPow[a - abc_min, x - xyz_min] = BigInteger.Pow(a, x);
然后您不需要在每次迭代时计算BigInteger.Pow
:
for (a = abc_min; a <= abc_max; a++)
{
for (b = a; b <= abc_max; b++)
{
for (c = abc_min; c <= abc_max; c++)
{
for (x = xyz_min; x <= xyz_max; x++)
{
p1 = abcPow[a - abc_min, x - xyz_min];
for (y = xyz_min; y <= xyz_max; y++)
{
p2 = abcPow[b - abc_min, y - xyz_min];
for (z = xyz_min; z <= xyz_max; z++)
{
p3 = abcPow[c - abc_min, z - xyz_min];
if (p1 + p2 == p3)
{
Console.WriteLine("{0}^{1}+{2}^{3}={4}^{5}\n", a, x, b, y, c, z);
num++;
Console.ReadKey();
Console.WriteLine("----------------------------\n");
if (a != b)
{
Console.WriteLine("{0}^{1}+{2}^{3}={4}^{5}\n", b, y, a, x, c, z);
num++;
Console.ReadKey();
Console.WriteLine("----------------------------\n");
}
}
else if (p1 + p2 < p3)
{
// No more solutions could be found for the given z
break;
}
}
}
}
}
}
}
注意p1 = ...
和p2 = ...
移出内循环,因为它们不依赖于内循环的变量。
修改强>
从a^x + b^y = b^y + a^x
开始,从b
开始a
循环是有意义的,当找到解决方案时,如果a != b
,则输出两个解决方案。
在我的机器上,它加快了~20
次的计算。