问题
一个
m
位的整数,有多少可以被整数
- 测试输入
1 3 - 测试输出
4
分析1
这个问题显然不能穷举所有的情况。数论中的模加法运算有这样的性质(对乘法也是一样):
由此可见,一个数的取模问题可以拆分成两个求和数的取模问题,这显然属于动态规划能够解决的问题。对于一个
m
位的整数
令
(xi−1×10+xi) mod n====[(xi−1×10) mod n+xi] mod n{[(xi−1 mod n)×10] mod n+xi} mod n[(j×10) mod n+xi] mod n(j×10+xi) mod n
由此定义
c[i,j]
为前
i
位数模
代码1
import java.util.Scanner;
public class ModNums {
static void solution(long[][] c, int m, int n) {
for (int i = 0; i < n; i++) {
c[0][i] = 0L;
}
c[0][0] = 1L;
for (int i = 1; i <= m; i++) {
for (int j = 0; j < n; j++) {
for (int k = 0; k < 10; k++) {
c[i][(j * 10 + k) % n] += c[i - 1][j];
}
}
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();
int n = sc.nextInt();
long[][] c = new long[m + 1][n];
solution(c, m, n);
System.out.println(c[m][0]);
}
}
变形
一个
m
位的整数,其中有某些位不确定,用”X”表示,有多少可以被整数
- 测试输入
999999999X 3 - 测试输出
4
分析2
整体和原问题一样,只是不确定的位才需要穷举一遍,确定的位直接更新即可。
代码2
import java.util.Scanner;
public class AmbiguousNums {
static void solution(long[][] c, String seq, int n) {
int length = seq.length();
for (int i = 0; i < n; i++) {
c[0][i] = 0L;
}
c[0][0] = 1L;
for (int i = 1; i <= length; i++) {
char ch = seq.charAt(i - 1);
for (int j = 0; j < n; j++) {
if (ch == 'X') {
for (int k = 0; k < 10; k++) {
c[i][(j * 10 + k) % n] += c[i - 1][j];
}
} else {
int k = ch - '0';
c[i][(j * 10 + k) % n] += c[i - 1][j];
}
}
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String seq = sc.next();
int length = seq.length();
int n = sc.nextInt();
long[][] c = new long[length + 1][n];
solution(c, seq, n);
System.out.println(c[length][0]);
}
}