5

因此,在 Project Euler 中,问题 4陈述如下:

回文数的两种读法都是一样的。由两个 2 位数字的乘积构成的最大回文数是 9009 = 91 99。

找出由两个 3 位数字的乘积构成的最大回文数。

我尝试了以下方法:

    #include <stdio.h>
    #include <stdlib.h>

    int check(int result)
    {
        char b[7];
        sprintf(b, "%d", result);
        if (b[0] == b[5] && b[1] == b[4] && b[2] == b[3])
        {
            return 1;
        }
        else 
        {
            return 0;
        }
    }

    int main () {
        int i;
        int g;
        int final;
        for (i = 999; i > 99; i--)
        {
            for (g = 999; g > 99; g--)
            {
                if (check(g*i) == 1)
                {
                    final = g*i;
                    goto here;
                }
            }
        }
        here:
        printf("%d", final);
}

但是,这不起作用。我得到的不是正确答案,而是 580085,我猜这至少是回文,但仍然不是正确答案。

让我从以下开始解释我的程序int main

  1. int i并且int g是我的乘数。他们就是那两个三位数。
  2. int final是将存储最大回文的数字。
  3. 我开始两个 for 循环,以获取每个数字的可能性。
  4. 当达到第一个回文时,我使用 goto 退出循环(可能不应该,但它不会对像这样的小程序产生太大影响)。
  5. 第一个回文应该是最大的回文,因为我从顶部倒数。

现在让我解释一下我的支票:

  1. 首先,因为这两个三位数相乘以确定一个字符需要保持该值的大小,所以我去计算器并乘以 999 * 999,结果是 6,然后我需要加一个,因为我发现从我之前发布的一个问题中,sprintf将一个\0角色放在最后。
  2. 好的,现在我有了一个 char 和所有内容,我复制了result(其中i*gin int main)并将其放入char b[7].
  3. 然后我只是b通过硬编码我需要检查的每个插槽来检查它是否等于它自己。
  4. 然后我相应地返回,1 为真,2 为假。

这对我来说似乎完全合乎逻辑,但是由于某些奇怪的原因它不起作用。有什么提示吗?

4

10 回答 10

13

这个假设是错误的:

第一个回文应该是最大的回文,因为我从顶部倒数。

你会999*100 = 99900在之前检查998*101 = 100798,所以很明显你不能指望它。

于 2010-07-14T22:16:14.327 回答
2

问题是你找到的第一个回文肯定不是更大的。

只是一个例子:

i = 900, g = 850 -> 765000
i = 880, g = 960 -> 844800

第一个较小,但由于您首先迭代 on i,然后g将首先发现它。

好的,它们不是回文,但概念是相同的..

于 2010-07-14T22:20:22.970 回答
2

我认为你正在从头到尾解决这个问题。从最高到最低生成回文然后通过分解它们来检查会更有效。第一个具有两个三位数的因素就是答案。

例如

  bool found = false;
  for (int i = 998; i >= 100; i--)
  {
    char j[7];
    sprintf(j,"%d",i);
    j[3]= j[2];
    j[4]= j[1];
    j[5]= j[0];
    int x =atoi(j);
    int limit = sqrt((float) x);
    for (int z = 999; z >= limit; z--)
    {
      if (x%z==0){
        printf("%d",x);
        found = true;
        break;
      }
    }
    if (found) break;
  }
于 2010-07-14T22:45:20.857 回答
1

第一个回文应该是最大的回文,因为我从顶部倒数

问题是您可能已经找到了一个 largei和 small的回文g。可能有一个更大的回文是以下产品的j产物k

i > j and
g < k

(我希望这是有道理的)。

于 2010-07-14T22:19:12.963 回答
1

Java实现:

public class Palindrome {

    public static void main(String[] args)
     {       int i, j;
            int m = 1;
            int k =11;
            boolean flag = false;

            while (true)
            {;
                if (flag) j = m + 1;
                else j = m;

                for (i = k; i > 0; i--)
                {

                    j++;



                    int number, temp, remainder, sum = 0;
                    number = temp = (1000 - i) * (1000 - j);

                    while (number > 0)
                    {
                        remainder = number % 10;
                        number /= 10;
                        sum = sum * 10 + remainder;
                    }

                    if (sum == temp)
                    {
                        System.out.println("Max value:"+temp);

                        return;
                    }


                }

                if (flag)
                    m++;
             k=k+11;
                flag = !flag;
            }

     }

}
于 2011-02-06T17:53:17.120 回答
0

关于性能的一句话。您有可能复制许多产品,因为您使用的是非常简单的嵌套循环方法。例如,您从 999*999 开始,然后是 999*998,等等。当内循环结束时,您将减少外循环并从 998*999 重新开始,这与 999*998 相同。

实际上,您要做的是使用与当前外部循环值相同的值启动内部循环。这将消除您的重复操作。像这样的东西...

for (i = 999; i > 99; i--)
{
  for (g = i; g > 99; g--)
  {
...

但是,正如 Emilio 指出的那样,您认为您找到的第一个回文将是答案的假设是不正确的。显然,您需要首先计算最大的数字。所以你应该按这个顺序尝试它们;999*999、999*998、998*998、999*997、998*997等...

尚未对其进行测试,但我认为您想要这样的东西(伪代码):

x = 999;
n = 0;

while (++n <= x)
{
  j = x;
  k = j - n;

  while (j >= k)
  {
    y = j-- * k;
    if (check(y))
      stop looking
  }
}
于 2010-07-14T22:40:06.623 回答
0

我发现这篇文章可能会对你有所帮助。它改进了蛮力方法。

于 2012-03-28T18:01:45.907 回答
0

以上提供的所有答案都非常好,但我仍然无法限制自己编写代码。@thyrgle 发布的代码绝对完美。他需要做的只是稍微修正一下,检查哪个产品是最大的。代码可以是

int i,j,max=0,temp;
for(i=999;i>=100;i--){
    for(j=i;j>=100;j--){
        temp=i*j;
        if(isPalin(temp) && temp>max){
            max=temp;
        }
    }
}
cout<<max<<"\n";
于 2014-10-29T07:46:15.973 回答
0
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int a[6];

void convertToString(int xy){
    int i,t=100000;
    for(i=0;i<6;i++){
        a[i]=xy/t;
        xy = xy % t;
        t=t/10;
    }
}

int check(){
    int i;
    for(i=0;i<3;i++){
        if(a[i]!=a[6-i]){
            return 0;
        }
    }
    return 1;
}

void main(){
    int x,y,xy,status=0;
    int i=0,j=0,p=0;
    for(x=999;x>99;x--){
        for(y=x;y>99;y--){
            xy=x*y;
            convertToString(xy);
            status = check();
            if(status==1){
                if(xy>p){
                    p=xy;
                    i=x;
                    j=y;
                }
            }
        }
    }

    printf("\nTwo numbers are %d & %d and their product is %d",i,j,p);

}
于 2015-03-26T19:53:07.280 回答
0
x,y=999,999

k=0

pal=[]

while (y>99):
    while (x>=100):
        m=x*y
        n=x*y
        while (n!=0):
            k=k*10+(n%10)
            n=int(n/10)
        if(m==k):
            if k not in pal:
                pal.append(k)
        x=x-1
        k=0
    else:
        y,x=y-1,999


pal.sort()
print(pal)

它给出了 906609 作为最大的回文数

于 2018-01-13T12:06:22.447 回答