[Project Euler] Problem 29

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

2 2=4, 2 3=8, 2 4=16, 2 5=32
3 2=9, 3 3=27, 3 4=81, 3 5=243
4 2=16, 4 3=64, 4 4=256, 4 5=1024
5 2=25, 5 3=125, 5 4=625, 5 5=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 >

using namespace std;

int getTerms( int );

int getNum( int , int );

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

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行。

你可能感兴趣的:(project)