【问题标题】:Algorithm in C - playing with numbers - number with 3 in units placeC中的算法 - 玩数字 - 3在单位位置的数字
【发布时间】:2011-10-31 02:04:28
【问题描述】:

我在一次采访中遇到了这个问题。 任何单位位置为 3 的数字至少有一个包含所有 1 的倍数。例如,3 的倍数是 111,13 的倍数是 111111。给定一个以 3 结尾的数字,我被问到找到包含全 1 的倍数的最佳方法。 现在有一种简单的方法是可能的,您不考虑空间问题,但随着数量的增长,有时即使不考虑,int(或 long int在那!)在C中不能容纳那个倍数。 在 C 中实现这种算法的最佳方法是什么?

【问题讨论】:

  • 是的,很抱歉打错了。已编辑。
  • 怎么样:133的倍数?
  • 十八个:111111111111111111
  • 其实不用大数除法或乘法...

标签: c algorithm numbers


【解决方案1】:

如果有人正在寻找 Java 解决方案:

public static void main(String[] args) {

    int input = 55333;
    int minAllOnesNum = 1;
    int nextAllOnesNum= minAllOnesNum;  

    int numberof1s=1;
    int count = 0;
    while(true)
    {
        count++;

        if(nextAllOnesNum%input == 0 ) 
        {
            break;  
        }

        nextAllOnesNum = nextAllOnesNum*10 + 1;

        if(nextAllOnesNum>=input) {
            nextAllOnesNum%=input;
        }
        numberof1s++;
    }


    System.out.println("count : " + count);

    for(int i=1; i<=numberof1s; i++) {
        System.out.print("1");
    }
}

【讨论】:

  • 一个好的答案将始终包括解释为什么这会解决问题,以便 OP 和任何未来的读者可以从中学习。
【解决方案2】:

就像 Bolo 的解决方案一样,具有更简单的相等性 M(i+1) = 10*M(i) + 1。这是python版本:

def ones( n ):
  i = m = 1
  while i <= n:
    if m == 0:
      return i
    m = ( ( 10 * m ) + 1 ) % n
    i += 1
  return None

【讨论】:

  • 太棒了!除非有封闭式公式,否则这是最快(且非常优雅)的算法。我也喜欢你避免无限循环的方式。
  • @Bolo 序列 M(i) 最多可以有 n 个不同的值,因此无需进一步搜索。
  • @Ante 是的,我明白了。正如我所说,这是一个非常好的观察结果!
  • 第 4 行的 m%n 是不必要的,因为你已经在第 7 行做了,之后 m 的值没有改变,所以你可以直接检查 m==0。
【解决方案3】:

更新:整合 Ante 的观察结果并将答案社区设为 wiki。

像往常一样,在这类问题中,编写任何可行的蛮力算法都相对容易,但更多的是数学。你用铅笔和纸做,你可以获得更好(更快)的算法。

让我们使用简写符号:让 M(i) 表示 1111...1(i 个)。

给定一个数 n(假设 n = 23),你想找到一个数 m,使得 M(m) 可以被 n 整除。一个直接的方法是检查 1, 11, 111, 1111, ... 直到我们找到一个能被 n 整除的数。注意:可能存在 closed-form solution 用于在给定 n 的情况下找到 m,因此这种方法不一定是最佳的。

当迭代 M(1), M(2), M(3), ... 时,有趣的部分显然是如何检查给定数是否可被 n 整除。你可以实现long division,但arbitrary-precision arithmetic 很慢。相反,请考虑以下事项:

假设您从之前的迭代中已经知道M(i) mod n 的值。如果M(i) mod n = 0,那么你就完成了(M(i) 是答案),所以我们假设它不是。你想找到M(i+1) mod n。由于M(i+1) = 10 * M(i) + 1,您可以轻松计算M(i+1) mod n,因为它是(10 * (M(i) mod n) + 1) mod n。即使对于较大的 n 值,也可以使用固定精度算术计算。

这是一个计算可被 n 整除的最小数目的函数(从 Ante 的 Python 答案翻译为 C):

int ones(int n) {
        int i, m = 1;
        /* Loop invariant: m = M(i) mod n, assuming n > 1 */
        for (i = 1; i <= n; i++) {
                if (m == 0)
                        return i;  /* Solution found */
                m = (10*m + 1) % n;
        }
        return -1;  /* No solution */
}

【讨论】:

  • 我刚刚实现了长除法,才看到你的帖子,发现23的倍数是1111111111111111111111。但是你的最后一段在我看来很有趣,需要检查一下
  • +1 在写我的之前我没有看到你的答案,但就是这样,解决方案是 i 的最小数量,使得 (10^i mod n) 的总和是 n 的倍数
  • M(i+1) = 10*M(i) + 1,不需要10^i mod n序列。
  • @Ante 太棒了!您的评论产生了一个更快、更优雅的解决方案。
  • 你能解释一下为什么 m 被初始化为 1 以及为什么我会一直迭代到 n 吗?
【解决方案4】:

您不必以“大数字”的方式考虑这个问题。只要拿一张纸,用手做乘法,很快你就会找到最好的答案:)

首先,让我们考虑3x

的结果的个位
 x  0 1 2 3 4 5 6 7 8 9

3x  0 3 6 9 2 5 8 1 4 7

因此,关系是:

what we want 0 1 2 3 4 5 6 7 8 9
 multiplier  0 7 4 1 8 5 2 9 6 3

第二,做乘法,不要保存不必要的数字。以 13 为例,要生成 '1',我们必须选择乘数 7,所以

13 * 7 = 91

好吧,保存'9',现在我们面临的是9。我们必须选择乘数[(11-9)%10]:

13 * 4 = 52, 52 + 9 = 61

继续!保存“6”。选择乘数[(11-6)%10]

13 * 5 = 65, 65 + 6 = 71

保存“7”。选择乘数[(11-7)%10]

13 * 8 = 104, 104 + 7 = 111

保存“11”。选择乘数[(11-11)%10]

13 * 0 = 0, 0 + 11 = 11

保存“1”。选择乘数[(11-1)%10]

13 * 0 = 0, 0 + 1 = 1

保存“0”。哇~!当你看到“0”时,算法结束!

最后,如果您在上面的一个步骤中打印一个“1”,您将在此处得到一个“1”字符串答案。

【讨论】:

  • 只使用整数和乘法——很好的解决方案!
【解决方案5】:

23的倍数是1111111111111111111111

#include <stdio.h>

int
main () {
        unsigned int ones = 1;
        double result, by = 23, dividend = 1;
        while (dividend) {
            result = dividend / by;
                if (result < 1) {
                    dividend = dividend * 10 + 1;
                        ++ones;
                } else {
                    dividend -= by * (int)result;
                }
        }
        while (ones--) {
            printf("1");
        }
        printf("\n");
    return 0;
}

【讨论】:

  • 没有无限循环检查,所以当然必须加上。
猜你喜欢
  • 2021-05-08
  • 2021-12-18
  • 2014-08-25
  • 1970-01-01
  • 2018-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-02
相关资源
最近更新 更多