这是关于项目欧拉问题的问题。 您可以在此处找到问题的描述:https://projecteuler.net/problem=29
好的,首先,让我澄清一下我已经解决了这个问题,我只是在寻找一种更多基于数学的替代解决方案。
第二,为了不破坏任何尚未解决的问题,如果你还没有解决,请不要继续。 :)
所以,我使用Python解决了这个问题,因为它支持大数字和列表推导,我能够想出一个单行:
print(len(set([a ** b for a in range(2, 101) for b in range(2, 101)])))
现在,我试图通过使用更多的数学知识在C中解决它(C本身不支持大数字或列表推导)。 我遇到了这个帖子:PROJECT EULER #29接受的答案给了我一些想法,我想出了这个代码:
int main(void) {
int found[1000]; // an array where I hold the found values(0 or 1)
int e, b, i, count, x;
count = 0; // number of duplicates
x = 3;
for(i = 0; i < 1000; i++)
found[i] = 0;
for(e = 1; (int)pow(x, e) <= 100; e++) {
for(b = 2; b <= 10; b++) {
if(found[e * b]) // if the value has been found, then we have duplicate
count++;
found[e * b] = 1; // mark that we found the value
}
}
printf("count: %d\n", count);
return 0;
}
使用此代码,我正在做您在答案底部可以看到的内容
上面,他展示了一些关于如何找到重复项的图表
x = 3,基于他之前解释的内容。我想做同样的事情。现在,如果你运行我的代码,
它根据上述答案的图表正确输出13,这是重复的数量。
所以,我试图扩展它以解决实际的项目euler问题,因为如果我能够找到重复的数量,那么我将从数字99 * 99中减去它(这是可能的功率组合,因为2 &lt; = a&lt; = 100且2&lt; = b&lt; = 100)这将是答案。结果是:
int main(void) {
int found[1000];
int e, b, i, count, x;
count = 0;
for(x = 2; x <= 100; x++) {
for(i = 0; i < 1000; i++)
found[i] = 0;
for(e = 1; (int)pow(x, e) <= 100; e++) {
for(b = 2; b <= 100; b++) {
if(found[e * b])
count++;
found[e * b] = 1;
}
}
}
printf("count: %d\n", count);
return 0;
}
如果你注意,那些变化是我循环所有xs从2到100而b不是从2到10但是从2到100。 但是,程序打印814,这是不正确的。它应该是618。 任何帮助都非常感谢!我可能两次重复一些重复,但在哪里?代码有什么问题?此外,如果您有任何有助于构建新算法的数学解释,我们也非常感激!
编辑:
我忘了提到的一件事是,如果不是放下:
for(x = 2; x <= 100; x++)
我这样做:
for(x = 2; x <= 6; x++)
即停止到6,它打印正确的答案。而这更令人感到奇怪。
EDIT2 :
我还要注意,对于8和9(而不是100),它给出了正确的结果。分别为44和54。
答案 0 :(得分:4)
vector<int> calcCache(int rangeStart, int rangeEnd)
{
int maxBase = rangeEnd*rangeEnd;
int maxStartPow = 1;
while (maxBase > 0)
{
maxBase /= 2;
maxStartPow++;
}
maxStartPow /= 2;
vector<bool> seen(maxStartPow*rangeEnd, false);
int i = rangeStart;
vector<int> cahce;
int maxprev = 0;
int gap = 1;
int startpow = 2 * gap;
int j = pow(i, startpow);
int diff = rangeEnd - rangeStart;
int maxCurrent = diff*gap + startpow;
while (j <= rangeEnd*rangeEnd)
{
int currPow = startpow;
int k = 0;
int currRes = 0;
while (k <= diff)
{
if (!seen[currPow])
{
currRes++;
}
seen[currPow] = true;
currPow += gap;
k++;
}
cahce.push_back(currRes);
maxprev = currPow - gap;
gap++;
startpow = 2 * gap;
j = pow(i, startpow);
}
return cahce;
}
int distinctpowers(int rangeStart, int rangeEnd)
{
vector<bool> arr(rangeEnd*rangeEnd + 1, false);
int res = 0;
vector<int> cache = calcCache(rangeStart, rangeEnd);
for (int i = rangeStart; i <= rangeEnd; i++)
{
if (!arr[i*i])
{
int maxprev = 0;
int gap = 1;
int startpow = 2 * gap;
int j = pow(i, startpow);
int diff = rangeEnd - rangeStart;
int maxCurrent = diff*gap + startpow;
while (j <= rangeEnd*rangeEnd)
{
int currPow = startpow;
res += cache[gap - 1];
maxprev = currPow - gap;
arr[j] = true;
gap++;
startpow = 2 * gap;
j = pow(i, startpow);
}
}
}
return res;
}
您可以为此代码添加许多增强功能,例如使用位向量而不是bool数组。
3 2 ,3 3 ,3 4 ,3 5 ,3 6 ,3 7 ,3 8 ,3 9 ,3 10
3 4 ,3 6 ,3 8 ,3 10 ,3 12 ,3 14 ,3 16 ,3 18 ,3 20
5 2 ,5 3 ,5 4 ,5 5 ,5 6 ,5 7 ,5 8 ,5 9 ,5 10
6 2 ,6 3 ,6 4 ,6 5 ,6 6 ,6 7 ,6 8 ,6 9 ,6 10
7 2 ,7 3 ,7 4 ,7 5 ,7 6 ,7 7 ,7 8 ,7 9 ,7 10
10 2 ,10 3 ,10 4 ,10 5 ,10 6 ,10 7 ,10 8 ,10 9 ,10 10
您是否注意到权力序列为每个新基数重复自我,并且基数2的序列中的最大数字
所以我们需要保存基础2的结果并将其重新用于另一个基础,这就是缓存的想法。
缓存中还有一件事是你需要弄清楚你有多少行2。所以从最大基数开始,每次除以2得到10 * 10,直到它变为零,但是这将给你最大基数2的最大功率作为最后一行的开始,这是我们的最后2 6 你开始从2到6的力量,每一行增加2,所以我们需要将结果除以2
int maxBase = rangeEnd*rangeEnd;
int maxStartPow = 1;
while (maxBase > 0)
{
maxBase /= 2;
maxStartPow++;
}
maxStartPow /= 2;
之后我们需要跟踪我们看到的功率,你可以遇到的最大功率是maxStartPow * rangeEnd。
vector<bool> seen(maxStartPow*rangeEnd, false);
然后我们开始在我们的基础中逐行进行,在这种情况下2 ,每一行记住我们看到的力量,当我们看到新的力量时,我们增加了这条线的结果。
这段代码最重要的部分是,在计算每一行之后我们需要存储它,因为我们将在主要问题中重用它。
int maxprev = 0;
int gap = 1;
int startpow = 2 * gap;
int j = pow(i, startpow);
int diff = rangeEnd - rangeStart;
int maxCurrent = diff*gap + startpow;
while (j <= rangeEnd*rangeEnd)
{
int currPow = startpow;
int k = 0;
int currRes = 0;
while (k <= diff)
{
if (!seen[currPow])
{
currRes++;
}
seen[currPow] = true;
currPow += gap;
k++;
}
cahce.push_back(currRes);
maxprev = currPow - gap;
gap++;
startpow = 2 * gap;
j = pow(i, startpow);
}
之后我们回到我们的distinguishedictPowers函数并逐个基地,逐行逐行,并从缓存函数重用我们的计算