加载中...

P1037 [NOIP2002 普及组] 产生数

[P1037 NOIP2002 普及组] 产生数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

思路:

  1. 先观察数据范围,超出 long 的数据类型大小的上限,所以不能简单的将其简单定义为 long 类型来接受数据。这里需要考虑高精度来解决
  2. 找出一个数字共有多少种变换的可能个数
  3. 然后相乘即为最后所组成的多位数的个数

涉及算法:

  1. Floyd
  2. 高精度
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]);
		}
	}
}

posted @ 2023-03-06 21:37  ChuenSan  阅读(82)  评论(0编辑  收藏  举报