模考T2 题解

这道题目有人往数学去想了……但是正解是 dp 哦~

我们来讲解 dp 的要素!

  1. 定义: dp[i][j] 为当数码和为 i 时,模 zj 时有几个满足要求的数。
  2. 遍历:三层循环,第一层,枚举数码和,第二层枚举余数,第三层枚举新添加在末尾的数。
  3. 状态转移:设 i 为当前的数码和 j 为当前的余数 k 为要新添加的数字。那么
    dp[i+k][(j\times 10+k)\ \mathrm{mod}\ z]=(dp[i+k][(j\times 10+k)\ \mathrm{mod}\ z]+dp[i][j])\ \mathrm{mod} \ 1000000007
    因为我们将当数码和为 i 余数为 j 的数在末尾添加一个数 k 的时候数码和变为 i+k 余数变为 (j\times 10+k)\ \mathrm{mod}\ z
  4. 初始化: dp[0][0] 只有一种情况所以将它初始化为 1
  5. 答案: dp[y][0]

伪代码:

    dp[0][0]=1;//初始化
	for(int i=0;i<y;i++){//枚举数码和
		for(int j=0;j<z;j++){//枚举余数
			if(dp[i][j]==0)continue;//若没有可能直接跳过
			for(int k=1;k<=9;k++){//因为没有 0 所以只能枚举 1~9
				if(i+k<=y){//判断会不会超出边界
                   //状态转移
			}
		}
	}
	cout<<dp[y][0];//输出答案

代码时间复杂度:时间主要开销在三层循环所以时间复杂度为 O(y\times z\times 9)

代码空间复杂度:主要用于存储 dp 数组空间复杂度为 O(50005\times 500)

2 个赞

@王建力

最后应该%1000000007

1 个赞

@陈梓豪 谢谢提醒已修改