在给定间隔中查找a,b,c,x,y,z的所有可能值,使得a ^ x + b ^ y = c ^ z

时间:2014-10-25 15:48:23

标签: c# optimization console-application

我想制作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();
    }
}

}

2 个答案:

答案 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次的计算。