计算数字x的位数,其数字和等于x*m的数字和

Count the number of number x that has digit sum equal the digit sum of x*m

本文关键字:数字 计算      更新时间:2023-10-16

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

问题:

给定正数n(n<=18(和正数m(m<=100(。调用S(x(是x的位数之和。例如S(123(=6计数具有n个数字的整数x的数量,并且S(x(=S(x*m(

示例:

n=1,m=2结果=2

n=18,m=1结果=1000000000000000000

提前谢谢。

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

从最低有效数字(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、2和3(感谢@LouisRicci找到它们(,我们可以声明:

  1. 倍数位数和的重复周期从基数(9表示基数-10(的倒数第1位开始重复

  2. S(x)可以定义为:设a等于x mod 9,如果a为零,则取9为结果,否则取a您可以在下面的ES6片段中播放:

IN.oninput= (_=> OUT.value= (IN.value % 9) || 9);
IN.oninput();
Input x:<br>
<input id=IN value=123><br>
S(x):<br>
<input id=OUT disabled>

  1. 乘法规则:S(x * y) = S(S(x) * S(y))

  2. S(x)S(x*m)对于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);

由于情况为零,加一:

result++;

这是一个ES6解决方案:

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();
Input n: (number of digits)<br>
<input id=N value=1><br>
Input m: (multiplicative number)<br>
<input id=M value=2><br>
F(n,m):<br>
<input id=OUT disabled><br>