P1037 [NOIP2002 普及组] 产生数
[P1037 NOIP2002 普及组] 产生数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
思路:
- 先观察数据范围,超出 long 的数据类型大小的上限,所以不能简单的将其简单定义为 long 类型来接受数据。这里需要考虑高精度来解决
- 找出一个数字共有多少种变换的可能个数
- 然后相乘即为最后所组成的多位数的个数
涉及算法:
- Floyd
- 高精度
public class P1037 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String n = scanner.next();
int k = scanner.nextInt();
int[][] tag = new int[10][10];// 关系矩阵,能从 1-9 则 tag[1][9] = 1
int[] counts = new int[10];// 表示一个数可以有多少种变换,初始值应该全为 1 (应该包含自身)
for (int i = 0; i < k; i++) {
int a = scanner.nextInt();
int b = scanner.nextInt();
tag[a][b] = 1;
}
for (int mid = 0; mid < 10; mid++) {// Floyd 算法
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
if (tag[i][mid] == 1 && tag[mid][j] == 1) {
tag[i][j] = 1;
}
}
}
}
for (int i = 0; i < 10; i++) {
tag[i][i] = 1;// 自己到自己可达
for (int j = 0; j < 10; j++) {
if (tag[i][j] == 1) {
counts[i]++;
}
}
}
char[] nums = n.toCharArray();
// int res = 1;// 特别注意,这里要高精度,否则爆 int 无法 AC
int[] res = new int[101];// 0~100 共 101 个数据
res[0] = 1;// 高精度乘法
for (int i = 0; i < nums.length; i++) {
for (int j = 0; j < 101; j++) {
res[j] *= counts[nums[i] - '0'];
}
for (int j = 0; j < 101; j++) {
if (res[j] > 10) {
res[j + 1] += res[j] / 10;
res[j] %= 10;
}
}
}
int i = res.length - 1;
while (res[i] == 0) {// 去除多余的 0 ,这里的高位在后,低位在前
i--;
}
for (; i >= 0; i--) {
System.out.print(res[i]);
}
}
}