计算数字和等于x * m的数字和的数字x的数量

时间:2015-09-14 13:55:32

标签: c++ algorithm c++11 dynamic-programming

我试图解决以下问题但我被困住了。我认为这是一个动态编程问题。 你能提出一些想法吗?

问题:

给定正数n(n <= 18)和正数m(m <= 100)。 呼叫S(x)是x的数字之和。 例如S(123)= 6 计算具有n位且S(x)= S(x * m)

的整数x的数量

示例:

n = 1,m = 2结果= 2

n = 18,m = 1结果= 1000000000000000000

提前致谢。

2 个答案:

答案 0 :(得分:6)

首先,我们需要提出一个递归公式:

从最低有效数字(LSD)到最高有效数字(MSD),我们有一个有效的解决方案,如果在我们计算MSD之后,我们有S(x) = S(x*m)

要验证数字是否是有效的解决方案,我们需要了解三件事:

  • 数字S(x)
  • 的当前总和是多少
  • 数字S(x * m)
  • 的当前总和是多少
  • 当前数字是什么。

因此,要回答第一个和最后一个,这很简单,我们只需要维护两个参数sumdigit。要计算第二个参数,我们需要维护另外两个参数sumOfProductlastRemaining

  • sumOfProduct是当前的S(x * m)
  • lastRemaining(m * current digit value + lastRemaining) / 10
  • 的结果

例如,我们有x = 123m = 23

  • 第一位= 3

    sum = 3
    digit  = 0
    sumOfProduct += (lastRemaining + 3*m) % 10 = 9
    lastRemaining = (m*3 + 0)/10 = 6
    
  • 第二位= 2

    sum = 5
    digit = 1
    sumOfProduct += (lastRemaining + 2*m) % 10 = 11
    lastRemaining = (m*2 + lastRemaining)/10 = 5
    
  • 最后一位= 1

    sum = 6
    digit = 2
    sumOfProduct += (lastRemaining + m) % 10 = 19
    lastRemaining = (m + lastRemaining)/10 = 2
    

    这是最后一位数字sumOfProduct += S(lastRemaining) = 21

因此,x = 123m = 23不是有效数字。检查x*m = 2829 -> S(x*m) = S(2829) = 21

因此,我们可以使用状态为(digit, sum, sumOfProdut, lastRemaining)的递归公式。

因此,我们的动态编程状态为dp[18][18*9 + 1][18*9 + 1][200](因为m <= 100,因此lastRemaining不大于200)。

现在dp状态超过300 MB,但如果我们使用迭代方法,它会变小,使用大约30 MB

答案 1 :(得分:0)

此问题可以直接计算。

从这些文档:123 (感谢@LouisRicci找到它们),我们可以声明:< / p>

  1. 倍数的总和的重复周期开始在最后一位数字处重复,但是从基数开始重复(基数为10的基数为10)

  2. S(x)可以定义为:让a等于x mod 9,如果a为零,则取9作为结果,否则取{ {1}}。 您可以在下面的ES6代码段中播放:

  3. &#13;
    &#13;
    a
    &#13;
    IN.oninput= (_=> OUT.value= (IN.value % 9) || 9);
    IN.oninput();
    &#13;
    &#13;
    &#13;

    1. 乘法规则:Input x:<br> <input id=IN value=123><br> S(x):<br> <input id=OUT disabled>

    2. S(x * y) = S(S(x) * S(y))S(x)对于S(x*m)始终为真,这样就没有零结果。

    3. 考虑到上述陈述,我们应该为x=0计算乘数的总和的重复周期:

      S(m)

      答案是:

      int m = 88;
      int Sm = S(m); // 7
      
      int true_n_times_in_nine = 0;
      for (int i=1; i<=9; i++) {
          true_n_times_in_nine += i == S(i * Sm);
      }
      

      另外一个因为案例零:

      result = ((pow(10, n) / 9) * true_n_times_in_nine);
      

      这是ES6解决方案:

      &#13;
      &#13;
      result++;
      
      &#13;
      S= x=> (x % 9) || 9;
      TrueIn9= (m, Sm=S(m))=> [1,2,3,4,5,6,7,8,9].filter(i=> i==S(i*Sm)).length;
      F= (n,m)=> ~~(eval('1e'+n)/9) * TrueIn9(m) + 1;
      
      
      N.oninput= 
      M.oninput= 
      f=(_=> OUT.value= F(N.value | 0, M.value | 0));
      f();
      &#13;
      &#13;
      &#13;