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;
}