最短的数字可被数字M整除

时间:2015-12-14 19:39:36

标签: algorithm numbers divide number-theory

我正在研究一种算法,我很欣赏一些数学帮助。我不确定它是否完全是数学问题,或者它只是一些数据结构,问题将得到解决。 输入时,你得到数字M和数字N(除以空格);在N之后有N位数(0-9)。问题是找到一个可以从这些数字创建的最短数字,这些数字可以被你的M数整除。 例如输入:

7 2 1 3

输出:

133

仅仅因为133(并且只能使用的数字是1和3)可被7整除,它是可被7整除的最短数字。实际上,数字不需要最低,只是最短的。 如果没有可以从这些数字中产生的数字,请打印-1。 如果有一位天才数学家,请提前感谢:P

编辑: 没有空间限制,但任何输入的时间限制应为10秒,无论Big-O。

3 个答案:

答案 0 :(得分:2)

就个人而言,我会反过来谈论这个问题。取你的M号,然后乘以1.你能找到M * 1的数字吗?如果不是,则转到M * 2。你可以停在一些任意高的数字。如果您正在使用整数,则可以停止使用INT_MAX或其他任何内容。

编辑:您实际上可以停在INT_MAX-M。

答案 1 :(得分:2)

您可以通过使用模运算一次一位地搜索解决方案

来实现

我们可以认为这个问题是找到n个数字的序列d i ∈S enter image description here

如果我们完成所有算术模型,我们可以将其视为在模数m的整数空间上搜索值“0”的路径。搜索中的每个步骤都是通过在我们的数字上附加一个数字来计算的。 Horner's Method告诉我们

enter image description here

这意味着对于我们附加到数字的每个数字,我们将旧值乘以10,并添加新数字的值。乘以10和加上数字都很容易做到,因此我们一次建立一位数,我们可以跟踪它的值mod m。沿着数字构造的步骤根据它到达的值10来描述通过节点的“路径”。

我们将在这些路径上执行图搜索,以找到(0)的最短“路径”。因此,对于图搜索的每个步骤,我们计算长度为i的最短“路径”(即具有i个数字的最小数字),其以给定的“节点”结束(即,值mod m)。

例如,让我们假设我们的数字集是{1,3},m = 9。然后我们的搜索节点集将是{(0),(1),...,(8)}。对于每个节点,我们存储“到目前为止的最佳路径”以达到它。这仅仅意味着对于节点(k),我们存储到目前为止找到的最小数,等于k mod m。

在搜索的第一步,我们希望找到最小的1位数字,它等于0,1,...,8 mod 9中的每个值。因为我们唯一可用的数字是1和3,( 1)和(3)是第一步中唯一可达的节点,所有其他节点都不可达。

在第二步,我们试图找到最小的两位数字,它等于0,1,...,8 mod 9中的每个值。从Horner的方法,我们记得每两位数字只是10*p + d其中p是1位数字。因此我们可以通过取10*p + d来获得所有节点可以两步到达,其中p是1步可达的数,d∈S。对于任何节点(k),到“(k)的”最短路径“ ,即

的最小值10*p+d

enter image description here

将是p的最小值

enter image description here

即。

的最小p值(由d打破的关系)

enter image description here

但现在请注意,因为p是1位数字,所以从上一步开始我们存储了p的最小值,这个值为真。因此,我们不需要检查p的每个可能值,我们只需要检查p的值,这是前一步骤中某个节点的最小可能路径。

这个算法有很多理由,但最终,它只是意味着我们注意到了

shortest path to (1) is 1 so
   with d=1, (2) is reachable in length 11 (p=1, d=1 10p+d=11=2 mod 9)
   with d=3, (4) is reachable in length 13 (p=1, d=3 10p+d=13=4 mod 9)
shortest path to (3) is 3 so
   with d=1, (4) is reachable in length 31 (p=3, d=1 10p+d=31=4 mod 9)
   with d=3, (6) is reachable in length 33 (p=3, d=3 10p+d=33=6 mod 9)

因此,每个可到达节点的最短路径是

(1)->1
(3)->3
(2)->11
(4)->13
(6)->33

所有其他节点都无法访问。

在每次迭代中,我们可以重复同样的技巧,即i位数只是10 * p + d,其中p是(i-1) - 数字。所以我们只需要搜索上一步存储的p值,我们将保证找到最短路径长度< = i,即最小数量等于k mod m。

因此,每个步骤都可能增加可达节点的大小,如果0可以到达,我们找到了方程的最小解。但是,如果无法访问0,我们将如何判断何时停止搜索?关键是我们算法的每次迭代完全相同,所以如果在某次迭代中可达节点的集合不会改变,那么无论我们等待多久,我们都知道它永远不会再改变。因为存在有限数量的节点,我们知道要么最终必须达到零,要么我们的节点集必须达到固定限制,从而终止我们的算法。

所以为了完成我们的例子,我们有

shortest path to (2) is 11 so
   with d=1, (3) is reachable in length 111 (p=11, d=1 10p+d=111=3 mod 9)
   with d=3, (5) is reachable in length 13 (p=11, d=3 10p+d=113=5 mod 9)
shortest path to (4) is 13 so
   with d=1, (5) is reachable in length 131 (p=13, d=1 10p+d=131=5 mod 9)
   with d=3, (7) is reachable in length 133 (p=13, d=3 10p+d=133=7 mod 9)
shortest path to (6) is 33 so
   with d=1, (7) is reachable in length 331 (p=11, d=1 10p+d=331=7 mod 9)
   with d=3, (0) is reachable in length 333 (p=11, d=3 10p+d=333=0 mod 9)

这意味着我们找到了(0)的最短路径,即333。

空间复杂性:

对于每个值0< = i< m,我们需要存储一个数字和指向路径中前一个节点的指针,这将需要整体存储O(m)。

运行时间:

图中的每个节点都要求我们考虑每个数字的转换d∈S。因此运行时间将为O(m * r),其中r是可接受数字S的大小。

对解决方案的约束:

最后,我们可以使用该算法来限制解决方案的大小。由于搜索在最多m步之后终止,并且我们知道它将在i步骤中检查最大尺寸10 i 的解,我们知道解决方案必须以10 m

显然,这种算法适用于10以外的基础。

答案 2 :(得分:0)

我只是递归搜索这样的数字。问题是你需要一个很好的方法来阻止。我的算法我很难检查溢出。您可以选择更好的内容,例如您想要搜索的深度。

public static long find(int n, int[] digits, long current) {
    if (current > 0 && current % n == 0) {
        return current;
    }
    if (current < 0) {
        return Long.MAX_VALUE;//overflow
    }
    List<Long> all = new ArrayList<>();
    for (int i : digits) {
        long nc = current * 10 + i;
        all.add(find(n, digits, nc));
    }
    long found = Long.MAX_VALUE;
    for (long i : all) {
        if (i > 0) {
            found = Math.min(found, i);
        }
    }
    return found;
}

public static void main(String... args) {
    System.out.println("aaa");
    int d[] = {1, 3};
    System.out.println(find(7, d, 0));
}

数字的大小受长最大值的限制。您可以使用BigInteger长时间放置并尽可能多地使用