《训练指南》——6.12

Uva:11361

  数字和与倍数

  给定正整数a、b、k,你的任务是在所有满足a≤n≤b的整数n中,统计有多少个满足n自身是k的倍数,且n的各个位数上的数字(十进制)和也是k的倍数?

  分析:设f(x)是不超过x的非负整数满足题设要求的数量,对于这种求解一个区间上的解,则这道题目的解释f(b) – f(a-1),那么下面我们面临的问题就是如何求解f(x)。

  这里对于较大规模的问题,无非是a、b的取值较大,因此这里我们考察较大数值和较小数的情况存在着怎样的递推关系。

  而这种关系显然要基于题目给出的限制,我们需要表征每一种状态能够被k整除以及每一位上的数字之和能被k整除,因此我们需要扩充一下f(x)定义。

  设f(x,m1,m2)表示有x位“自由位”(这个概念后面建立递推关系的时候会给出具体含义),并且这种状态的某个确定数字余k的结果是m1,各位数上的数字和余k的结果是m2.那么对于具有较高位数的数字但是前几位数是确定的情况,我们是能够建立递推关系来缩小其问题规模的。举个例子来理解一下,对于数字22xxx,即表示[22000,22999]上的整数,这里就有三个“自由位”,即该位上能够取遍[0,9]。能够看到,这个区间上的解是与另一个较小规模的状态xxx是对应起来的,考虑到22xxx确定位数上的数字,可得这种状态的答案数是f(3,3,1)。

  而对于[1,a],我们可以建立一个多叉树,遍历最高位能够取得的整数以确定该位数上的数字以完成我们上面所描述的递推关系来缩小问题的规模。

  因此有如下的递推方程:

 

                                 

在编程过程中需要注意的是对于每个状态的参量m1,m2,在形成递推的时候可能会出现负数,只需进行(? + k)%k的操作即可。

  由于时间问题这里暂且给出递推方程的分析,代码暂且折叠。

原文地址:https://www.cnblogs.com/rhythmic/p/5585421.html