Problem 4:
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.
问题4:
回文数两个方向读得到的是同一个数。由2个2位数相乘得到的最大的回文数是9009=91*99。
找出由2个3位数相乘得到的最大的回文数。
分析:
思路1:遍历所有3位数的积,找出最大的回文数。[优点:简单,易快速实现。缺点:效率低。]
思路2:外循环由999向下遍历,内层只遍历大于等于外循环的数,计算乘积找出最大回文数。[优点:较思路1速度有提升]
思路3:如果使用32位int值,则思路2只能计算到2个4位数的最大回文数,为最大限度利用int值,对是否是回文数的判断采用以下方法:
根据乘法特点(被乘数的每1位分别乘以乘数,并将结果相加即可求出乘积),只需将被乘数的每1位乘以乘数,并将结果相加即可求出相应位的乘积值,因此可以用乘数的每1
位分别乘以被乘数,每求出1位数字将结果除以10。
5 4 3 2 5
* 5 4 3 2 5
------------------------------
2 7 1 6 2 5
1 0 8 6 5 0
1 6 2 9 7 5
-------------------------------
6 2 5
思路3程序如下:
解:
#define __METHOD_3 //#define __METHOD_2 #include <stdio.h> #include <math.h> #include <string.h> #include <malloc.h> #include <algorithm> using namespace std; #define PRINT printf #define DPRINT printf #define BOOL bool #define TRUE true #define FALSE false #define MAX_RES_BUF 21 typedef int INT; typedef void VOID; typedef char CHAR; #ifdef __METHOD_3 BOOL IsPalindromic(INT i, INT j, CHAR *szRes, INT len) //是回文数则返回TRUE,szRes返回该回文数 { if (NULL == szRes) return FALSE; //计算乘积 INT num, k; k = 0; num = 0; while ( j > 0) { num += i * (j % 10); if (k >= len) return FALSE; szRes[k++] = num % 10 + '0'; j /= 10; num /= 10; } while (num > 0) { szRes[k++] = num % 10 + '0'; num /= 10; } szRes[k] = '\0'; //反转串并比较 CHAR *szRev; szRev = (CHAR *)malloc(sizeof(CHAR)*(k+1)); strcpy(szRev, szRes); reverse(szRes, szRes+k); if (0 == strcmp(szRes, szRev)) //是回文数? { free(szRev); return TRUE; } free(szRev); return FALSE; } BOOL MaxPalindromic(INT num, CHAR *szRes, INT len) //szRes返回2个num位数字相乘的最大回文数 { if (NULL==szRes || num <= 0 || num>8) return FALSE; INT min, max; min = (int)pow(10, num-1); max = min * 10 - 1; INT i, j; CHAR buf[MAX_RES_BUF]; //结果(回文数) memset(szRes, 0, len); for (i=max; i>=min; i--) for (j=max; j>=i; j--) { if (IsPalindromic(i, j, buf, MAX_RES_BUF)) { if (strlen(buf) > strlen(szRes)) { if (strlen(buf) >= len) return FALSE; strcpy(szRes, buf); } else if (strlen(buf) == strlen(szRes)) { if (strcmp(buf, szRes) > 0) { if(strlen(buf) >= len) return FALSE; strcpy(szRes, buf); } } } } return TRUE; } #endif #ifdef __METHOD_2 BOOL IsPalindromic(INT n) //n是回文数则返回TRUE { INT nRev; INT nTem; nTem = n; nRev = 0; while(nTem > 0) { nRev = nRev * 10 + (nTem % 10); nTem /= 10; } if(nRev == n) return TRUE; return FALSE; } INT MaxPalindromic(INT num) //返回2个num位数字相乘的最大回文数 { if (num <= 0) return -1; INT min, max; min = (int)pow(10, num-1); max = min * 10 - 1; INT i, j; INT res; INT n; res = -1; for (i=max; i>=min; i--) for (j=max; j>=i; j--) { n = i * j; if (n>res && IsPalindromic(n)) res = n; } return res; } #endif INT main(INT argc, CHAR *argv[]) { INT num; #ifdef __METHOD_3 CHAR szRes[MAX_RES_BUF]; while (1) { PRINT("请输入数字位数(1~8),输入负数退出:\n"); scanf("%d", &num); if (num < 0) break; MaxPalindromic(num, szRes, MAX_RES_BUF); PRINT("%s\n", szRes); } #endif #ifdef __METHOD_2 INT res; while (1) { PRINT("请输入数字位数(1~4),输入负数退出:\n"); scanf("%d", &num); if (num < 0) break; res = MaxPalindromic(num); PRINT("%d\n", res); } #endif return 0; }