完美的力量检查

时间:2012-01-17 19:24:13

标签: c# algorithm math

完美的幂是N,其中A ^ B = N(A> = 1,B> = 2)

这是我的代码。我试图找出1和我选择的上限之间存在多少这些数字。

    static void Main(string[] args)
    {
        int PPwr_Count = 1; //number 1 is included by default.
        int Top_Limit = 1000000; //Can be any number up to 10^9
        for (int Number = 2; Number <= Top_Limit; Number++)
        {
            int myLog = (int)Math.Floor(Math.Log(Number, 2) + 1);
            for (int i = 2; i <= myLog; i++) 
            {
                //As a Math rule I only need to check below Base 2 Log of number
                int x = Convert.ToInt32(Math.Pow(Number, 1.0 / i));
                 if (Number == Math.Pow(x, i))
                 {
                     PPwr_Count++;
                     break;
                 }
                 else continue;
            }
        }
     } 

目前正在运作。可悲的是,在大约1,000,000次检查后,它变得非常缓慢。无论如何要提高这个算法的速度?

6 个答案:

答案 0 :(得分:7)

Math.Log很贵,Math.Pow很贵,双打很贵。你知道什么不贵吗?乘以整数。

一些理论加工:如果A ^ B == n且n <10 ^ 9且B> = 2且比最大A接近5 * 10 ^ 4。所以让我们拥有一套完美的力量。迭代从2而i * i&lt; = max_n,如果我没有设置,添加i * i,i * i * i,依此类推,而不是max_n。如果A = C ^ D,则A ^ B = C ^(B * D),并且已经设置。

static void Main(string[] args)
    {
        int PPwr_Count = 1; //number 1 is included by default.
        int Top_Limit = 1000000000; //Can be any number up to 10^9
        HashSet<int> hs = new HashSet<int>();

        for (int A = 2; A * A <= Top_Limit; ++A)
        {
            if (!hs.Contains(A))
            {
                //We use long because of possible overflow
                long t = A*A;
                while (t <= Top_Limit)
                {
                    hs.Add((int)t);
                    t *= A;
                    PPwr_Count++;
                }
            }
        }
        Console.WriteLine(PPwr_Count);
    }

编辑:在我的笔记本电脑上进行调试时,运行时间不到半秒。

答案 1 :(得分:3)

Math.Log(Number, 2) + 1移出for循环。

int myLog = (int)Math.Floor(Math.Log(Number, 2) + 1);
for (int i = 2; i <= myLog; i++) 

答案 2 :(得分:2)

我倾向于采用完全不同的方法。

首先,创建一个迭代器,枚举所有素数,直到最大大小的平方根。所以2,3,5,7,11 ......

更新:没有等待,并且工作正常。例如,这并不能将36作为一种完美的力量。

让我修改。

创建一个迭代器,枚举从2到最大大小的平方根的所有数字。

接下来,创建一个迭代器,它枚举特定给定数字的所有完美幂,直到最大大小。那是2 2 ,2 3 ,2 4 ,......

现在,将两个迭代器与select-many查询结合使用,以便生成:2 2 ,2 3 ,2 4 ,... 3 2 ,3 3 ,3 4 ,...,4 2 ,4 3 ,4 4 ,......

从结果查询中构建哈希集,以形成所有完美权力的并集,小于所有数字的最大大小,直到最大大小的平方根。

生成的哈希集的大小是您寻找的数字。

答案 3 :(得分:2)

从[素数列表]中的[2,...,sqrt(N)],B中搜索A和B的空间而不是N. A会更容易。

答案 4 :(得分:1)

另一个选择是,不是循环遍历所有数字并检查它们是否是一种力量,你可以做相反的事情:产生所有完美的力量。

因此,如果您从基数2开始,请计算2^12^2等。然后计算3^13^23^3等等上。您可能还希望将每个结果存储在HashSet中,以便消除双重结果。最后,计算就像hash.Count

一样简单

我不确定它的性能如何与你的代码叠加(它的空间效率肯定会降低),但它的另一个角度可能会起作用。

答案 5 :(得分:1)

我会尝试从另一个方向开始算法..

以a = 2和b = 2开始并经过每个b直到a ^ b&gt; max_limit

此方法的技巧是仅测试素数值

这种方法的技巧不是一个完美的权力的测试值(例如,不测试4,8,9等)