[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();
}
#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行。