完美的幂是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次检查后,它变得非常缓慢。无论如何要提高这个算法的速度?
答案 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^1
,2^2
等。然后计算3^1
,3^2
,3^3
等等上。您可能还希望将每个结果存储在HashSet
中,以便消除双重结果。最后,计算就像hash.Count
我不确定它的性能如何与你的代码叠加(它的空间效率肯定会降低),但它的另一个角度可能会起作用。
答案 5 :(得分:1)
我会尝试从另一个方向开始算法..
以a = 2和b = 2开始并经过每个b直到a ^ b&gt; max_limit
此方法的技巧是仅测试素数值
这种方法的技巧不是一个完美的权力的测试值(例如,不测试4,8,9等)