▼页尾

[Project Euler] Problem 29

Consider all integer combinations of ab for 2 ≤ a ≤ 5 and 2 ≤ b ≤ 5:

22=4, 23=8, 24=16, 25=32
32=9, 33=27, 34=81, 35=243
42=16, 43=64, 44=256, 45=1024
52=25, 53=125, 54=625, 55=3125

If they are then placed in numerical order, with any repeats removed, we get the following sequence of 15 distinct terms:

4, 8, 9, 16, 25, 27, 32, 64, 81, 125, 243, 256, 625, 1024, 3125

How many distinct terms are in the sequence generated by ab for 2 ≤ a ≤ 100 and 2 ≤ b ≤ 100?

这道题用 python 和 Java 可以很快得出结果,因为他们都有大数,初始化一个Set,往里面插入数字,最后计算Set中元素个数就可以了。

但用C++做就比较难,因为C++标准库难以计算像100**100这样的大数,我们可以实现自己的大数类,但这样就太困难了。

我们仔细思考后,会发现还有其他的一些方法。

我们发现,存在重复的数的底数都是能完全开方的数,这里我们说的重复的数是指后出现的数。

比如6 ** 4 = 36 ** 2,我们称36 ** 2为重复的数,而不是指6 ** 4 ,这里36能完全开方。

重复的数必然可以化为 a**b 这样的形式。其中a可以是2,3,5,6,7,10。

我们只需单独讨论这几种情况就可以了。

#include <iostream>
#include
<cmath>
#include
<set>

usingnamespace std;

int getTerms(int);

int getNum(int, int);

int main(){
cout
<< getTerms(100) << endl;
return0;
}

int getTerms(int num){
int sum = (num-1)*(num-1);
int factor[] = {2,3,5,6,7,10};
for(int i=0; i<6; i++){
sum
+= getNum(factor[i], 100);
}
sum
-=18*(num-1);
return sum;
}

int getNum(int factor, int num){
int i =1;
set<int> intSet;
while(pow(factor,i) <= num){
for(int j=2; j<=num; j++){
intSet.insert(i
*j);
}
i
++;
}
cout
<< factor <<'\t'<< intSet.size() << endl;
return intSet.size();
}

那个18是指 底为2,3,4,5,6,7,8,9,10,16,25,27,32,36,49,64,81,100的这18行。

posted @ 2011-06-29 10:38  xiatwhu  阅读(406)  评论(0编辑  收藏  举报
▲页首
西