状态dp[i]为长度为i位的所有数字不同的个数=长度为i-1位所有数字不同的个数*剩余可以选择的个数
package BDyNamicProgramming;
/**
* @Author Zhou jian
* @Date 2020 ${month} 2020/4/23 0023 16:07
*计算各个位数不同的数字的个数
*/
public class Problem357 {
public int countNumbersWithUniqueDigits(int n) {
if(n==0) return 1;
if(n==1) return 10;
int [] dp=new int[n+1];//从下标1开始使用
dp[1]=10;//一位数
dp[2]=81;//两位数:9*9
int sum=dp[1]+dp[2];
/**
* //两位数 三位数 四位数 五位数
//一位数 0-9 一个10种 dp[1]=10;
//两位数 dp[2] 就是从0-9选两个数字,有10*9种选法 减去0开头非法二位数的9种 81 加上dp[1] 为91
//三位数 dp[3]就是10*9*8 +dp[2]再减去以0开头的非法三位数9*8
//即 dp[3]=dp[2]+10*9*8-9*8;。
2 9*9
3 9*9*8
4 9*9*8*7
*/
for(int i=3;i<=n;i++){
//递推公式:状态转移方程
//新增第i位时,长度为i位的所有数字不同的个数
//=长度为i-1位所有数字不同的个数*剩余可供选择的个数
//组合的问题
dp[i]=dp[i-1]*(10-i+1);
sum+=dp[i];
}
return sum;
}
}