题目
A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.
Find the largest palindrome made from the product of two 3-digit numbers.
https://projecteuler.net/problem=1
分析
题目求由两三位数组成的最大回文数。(判断回文函数自定义为isPalindrome,maxPal表示最大回文,pal当前数积)
解法1(暴力):两个嵌套for i = 100 to 999循环枚举出所有的两位数乘积,再判断回文,比较最大。时间复杂度为O(N2)
解法2:可以看到解法1重复了计算了两次,如101*100 和100*101显然他们是一样的,可以将内循环初值设为外循环初值来解决。
解法3:从内循环判断看,if(isPalindrome){if(pal>maxPal)maxPal= pal }},我们要找最大的回文,可以先从最大的回文开始,
如果小于最大回文,则退出循环Break,不用执行多余的循环(内循环基数是递减的)。
解法4:观察回文:10201, 11211, 12221, 13231…..180081….
最大回文一定在6位数中,且
P = 100000x+10000y+1000z+100z+10y+x
= 100001x+1001y+1100z
= 11(9091x+910y+100z)
P = 180081 ==11x(9091x1+910x8+100x0)= 11 x 16371,所以6位数的回文一定能被11整除。根据这一条件可以对解法3进行优化。
Code
#include <iostream> #include <ctime> using namespace std; bool isPalindrome(int n); int f1(); int f2(); int f3(); int f4(); int main(){ double start, end; start = clock();//取开始时间 cout << "最大回文数为: " << f3()<<endl; end = clock();//取结束时间 cout << "运行时间为: "<<(end - start)/CLOCKS_PER_SEC << "s";//计算程序运行时间 return 0; } int f4(){ int maxPal = 0; int pal = 0; int i,j; for (i= 100; i <= 999; i++) { int j = 999,db=1,times; if (i == 913){ int a = 1; } if (i % 11 != 0){ j = 990;//三位数以内最大的11的倍数的数990开始。 db = 11;//divisible by 11 } while (i<=j) { times = i*j; if (times<maxPal)break; if (isPalindrome(times))//是回文数 { maxPal = times>maxPal ?times : maxPal; } j -= db; } } return maxPal; } int f3(){ int maxPal = 0; int times = 0; for (int i = 100; i < 999; i++) { int j = i; for (j; j < 999; j++) { times = i*j; if (times<maxPal)break; if (times) if (isPalindrome(times)){//是回文数 maxPal = times>maxPal ?times : maxPal; } } } return maxPal; } int f2(){ int maxPal = 0; int times = 0; int i, j; for (i = 100; i < 999; i++) { j = i; for (j; j < 999; j++) { times = i*j; if (isPalindrome(times)){//是回文数 maxPal = times > maxPal ? times : maxPal; } } } return maxPal; } int f1(){ int maxPal = 0; int times = 0; for (int i = 100; i < 999; i++) { for (int j = 100; j < 999; j++) { times = i*j; if (isPalindrome(times)){//是回文数 maxPal = times>maxPal ? times : maxPal; } } } return maxPal; } bool isPalindrome(int n){ int number = n; int reversed = 0; while (n>0) { reversed = 10 * reversed + n % 10; n /= 10; } return number == reversed; }
Mathematica
palQ[x_] := With[{ls = IntegerDigits[x]}, ls == Reverse[ls]]
Outer[Times, Range[100, 999], Range[100, 999]] // Flatten // Select@palQ // Max
只给除了暴力解法1的解法。其他解法的实现暂时不会…待填..
参考:Lster