Python 欧拉项目#29备选方案
这是一个关于项目Euler问题的问题。 您可以在此处找到问题的描述: 好的,首先,让我澄清一下,我已经解决了这个问题,我只是在寻找一个基于数学的替代解决方案Python 欧拉项目#29备选方案,python,c,algorithm,math,combinatorics,Python,C,Algorithm,Math,Combinatorics,这是一个关于项目Euler问题的问题。 您可以在此处找到问题的描述: 好的,首先,让我澄清一下,我已经解决了这个问题,我只是在寻找一个基于数学的替代解决方案 第二,为了不破坏尚未解决的问题,如果您尚未解决,请不要继续。:) 因此,我使用Python解决了这个问题,因为它支持大数字和列表理解,所以我能够想出一个单行线: print(len(set([a ** b for a in range(2, 101) for b in range(2, 101)]))) 现在,我试图用C语言解决这个问题,
第二,为了不破坏尚未解决的问题,如果您尚未解决,请不要继续。:) 因此,我使用Python解决了这个问题,因为它支持大数字和列表理解,所以我能够想出一个单行线:
print(len(set([a ** b for a in range(2, 101) for b in range(2, 101)])))
现在,我试图用C语言解决这个问题,方法是使用更多的数学知识(C语言本身不支持大数字或列表理解)。
我遇到了这样一条线索:接受的答案给了我一些想法,我想出了以下代码:
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;
}
int main(无效){
int found[1000];//保存找到的值(0或1)的数组
int e,b,i,count,x;
计数=0;//重复数
x=3;
对于(i=0;i<1000;i++)
发现[i]=0;
对于(e=1;(int)pow(x,e)而言,发现重叠数的观测值如下所示
首先,让我们将范围设置为从2到10,这样数字将类似于
22、23、24、25、26、27、28、29、210
32、33、34、35、36、37、38、39、310
42、43、44、45、46、47、48、49、410
52、53、54、55、56、57、58、59、510
62、63、66、65、66、67、68、69、610
72,73,77,75,77,77,78,79,710
82,83,88,85,88,88,88,89,810
92、93、94、95、96、97、99、99、910
102、103、104、105、106、107、108、109、1010
关键点是42=(22)2=24
因此,42、43、44、45、46、47、48、49、410将是
24、26、28、210、212、214、216、218、220
您是否注意到,在210之前,我们仍然有重复的数字,之后我们开始有一个新的数字
因此,用这个观察结果重写上面的数字,
22、23、24、25、26、27、28、29、210
32、33、34、35、36、37、38、39、310
24,25,28,210212,214,216,218,220
52、53、54、55、56、57、58、59、510
62、63、64、65、66、67、68、69、610
72、73、74、75、76、77、78、79、710
26、29、212、215、218、221、224、227、230
34,36,38,310312,314,316,318,320
102、103、104、105、106、107、108、109、1010
所以我们需要跟踪我们得到它的幂的数字,例如我们从22开始,数字是2,幂是2,增加幂的间隔是1。
它的代码是:
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;
}
在那之后,我们需要跟踪我们所看到的力量,你能遇到的最大力量是maxStartPow*rangeEnd
vector<bool> seen(maxStartPow*rangeEnd, false);
看到的向量(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);
}
intmaxprov=0;
int gap=1;
int startpow=2*间隙;
int j=功率(i,起动功率);
int diff=范围结束-范围开始;
int maxCurrent=diff*gap+startpow;
while(如果您想改进工作代码,应该转到:)谢谢你,我会考虑的!这只是因为它产生了错误的结果,所以没有真正起作用。我使用了与你完全相同的一条线性。但是,如果你想要一个更数学的方法,你可以不用计算幂。例如,64可以写为43和82,因为26=(23)**2=(2**2)**3.也就是说,我们写6=3*2=2*3,使用指数定律。当然,这适用于任何基数,而不仅仅是2,对于任何指数,你都可以将因子分解为不同的因子。现在你必须担心重复计算。是的,如果你看到我上面提到的线索,这就是他提到的,根据他的回答,我试图解决这个问题如你所说,基本问题是重复计算每次count
递增时,试着打印出x,e,b。然后你就可以看到你在数什么。你在这个答案上帮了我很多忙!但是,我认为有一些问题。首先,当你在代码之前从2到10做这个例子时,你把第7行的2^15重复计算,如果我没有错的话,就不会了。这就是对于rangeStart=2和rangeEnd=10,它返回68,而应该返回69(代码还将2^15计为重复)。最后,对于rangeStart=2和rangeEnd=100,这是PE问题,它返回9068,而它应该返回9183,可能是因为上述原因。尽管如此,感谢您的时间!:)是的,您是对的:)。我将更正它并添加另一个增强功能!在计算完基2的所有功率后,我们将保存结果并重新使用它以3、4、5为基数。等等。哦,老兄,你在这方面花了很多时间,非常感谢!!:)我也在尝试通过结合我们的代码思想来找到解决问题的方法!它正在工作!!:)如果你能解释一下它是如何工作的,或者发表一些评论,我将不胜感激,因为它是一个非常大的代码(虽然很快)。无论如何,非常感谢!!!
vector<bool> seen(maxStartPow*rangeEnd, false);
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);
}