【问题标题】:Finding the largest palindrome of the product of two three digit numbers problem求两个三位数乘积的最大回文问题
【发布时间】:2023-03-18 05:49:01
【问题描述】:

所以在 Project Euler 中,Problem 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 iint g 是我的乘数。它们就是那两个三位数。
  2. int final 是存储最大回文数的数字。
  3. 我开始了两个 for 循环,以获取每个数字的可能性。
  4. 当到达第一个回文时,我使用 goto 退出循环(可能不应该,但它不会对这样的小程序产生太大影响)。
  5. 第一个回文应该是最大的回文,因为我从顶部倒数。

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

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

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

【问题讨论】:

  • 你的“g”倒计时太快了——你可能会发现一个基于 999 * 101 的回文,但真正的答案更像是 997 * 867,它更大。
  • 一个提示:乘法是可交换的,因此您可以使用for (g = i; g &gt; 99; g--) 来避免同时测试999*100100*999
  • 顺便说一句,这是 goto 的合法用途
  • 解决这个问题的另一种方法是从 999*999 迭代到 100*100,然后对每个回文测试看它是否是两个 3 位数字的乘积。

标签: c algorithm palindrome


【解决方案1】:

这个假设是错误的:

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

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

【讨论】:

    【解决方案2】:

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

    只是一个例子:

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

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

    好吧,它们不是回文,但概念是一样的..

    【讨论】:

      【解决方案3】:

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

      例如

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

      【讨论】:

        【解决方案4】:

        第一个回文应该是最大的,因为我是从上往下倒数

        问题是您可能找到了一个大的i 和一个小的g 的回文。 jk 的乘积可能存在更大的回文,其中:

        i > j and
        g < k
        

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

        【讨论】:

          【解决方案5】:

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

          【讨论】:

            【解决方案6】:

            关于性能的一句话。您有可能复制许多产品,因为您使用的是非常简单的嵌套循环方法。例如,你从 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
              }
            }
            

            【讨论】:

              【解决方案7】:

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

              【讨论】:

                【解决方案8】:

                以上提供的所有答案都非常好,但我仍然无法限制自己编写代码。 @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";
                

                【讨论】:

                • 尽量不要拼错用户名(如 thyrgle)。尝试添加一些东西,比如不要摸索已知太小的产品:maxPalin = 100001 ... for (int lowerBound = maxPalin/i, j = i ; lowerBound &lt;= j ; j--)
                【解决方案9】:
                #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);
                
                }
                

                【讨论】:

                  【解决方案10】:
                  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 作为最大的回文数

                  【讨论】:

                    猜你喜欢
                    • 2014-01-31
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2017-12-04
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多