算法66------计算各个位数不同的数字个数【动态规划】

一、题目:计算各个位数不同的数字个数

给定一个非负整数 n,计算各位数字都不同的数字 x 的个数,其中 0 ≤ x < 10

示例:

输入: 2
输出: 91
解释: 答案应为除去 11,22,33,44,55,66,77,88,99 外,在 [0,100) 区间内的所有数字。

思路:动态规划

dp[i]表示 i 位数范围内【0,10^i】各位数字都不同的数字 x 的个数。

  • 当 n = 1 时, 只有 0 符合条件, 当 n = 10 时, 0 - 9 符合条件 (10个);
  • 当 n >= 2 时,记 f( n )为 [ 0, 10^n )范围内满足条件的数值个数,记 g( k ) 为 k位数中满足条件的数值个数, 则 f(n) = g(1) + g(2) + g(3) + ... +g(n) = f (n - 1) + g (n),

而 g(n) 属于组合问题, g(n) = 9 * 9 * 8 * 7 *...... * (11 - n),第一个“9”代表最高位上可选择的数为“ 1 ~ 9”九个,0 不可选,第二个“9”代表第二位上可选择的数为“0 ~ 9”中除去高位所选的其他九个数,依次类推,第 n 位上可选的数有 ( 11 - n ) 个。

即,dp[0] = 10,dp[0]表示n=1时,结果是10

dp[1] = 91,dp【1】表示n = 2时,结果为dp[0] + 9*9 = 91

dp[2] = 739,dp【2】表示n=3时,结果为dp[1] + 9 * 9 * 8 = 91 + 648 = 739

代码:

def countNumbersWithUniqueDigits(n):
    if n == 0:
        return 1
    dp = [0] * n
    dp[0] = 10
    for i in range(1,n):
        fi = 9
        for j in range(9,9-i,-1):
            fi *= j
        dp[i] = dp[i-1] + fi
    return dp[-1]
n =3
countNumbersWithUniqueDigits(n)

原文地址:https://www.cnblogs.com/Lee-yl/p/10057696.html

时间: 2024-10-08 16:34:24

算法66------计算各个位数不同的数字个数【动态规划】的相关文章

357 Count Numbers with Unique Digits 计算各个位数不同的数字个数

给定一个非负整数 n,计算各位数字都不同的数字 x 的个数,其中 0 ≤ x < 10n.示例:给定 n = 2,返回 91.(答案应该是除[11,22,33,44,55,66,77,88,99]外,0 ≤ x < 100 间的所有数字) 详见:https://leetcode.com/problems/count-numbers-with-unique-digits/description/ C++: class Solution { public: int countNumbersWith

[Swift]LeetCode357. 计算各个位数不同的数字个数 | Count Numbers with Unique Digits

Given a non-negative integer n, count all numbers with unique digits, x, where 0 ≤ x < 10n. Example: Input: 2 Output: 91 Explanation: The answer should be the total numbers in the range of 0 ≤ x < 100,   excluding 11,22,33,44,55,66,77,88,99 给定一个非负整数

[LeetCode] Count Numbers with Unique Digits 计算各位不相同的数字个数

Given a non-negative integer n, count all numbers with unique digits, x, where 0 ≤ x < 10n. Example: Given n = 2, return 91. (The answer should be the total numbers in the range of 0 ≤ x < 100, excluding [11,22,33,44,55,66,77,88,99]) Hint: A direct

给出一个区间[a, b],计算区间内“神奇数”的个数。 神奇数的定义:存在不同位置的两个数位,组成一个两位数(且不含前导0),且这个两位数为质数。 比如:153,可以使用数字3和数字1组成13,13是质数,满足神奇数。同样153可以找到31和53也为质数,只要找到一个质数即满足神奇数。

给出一个区间[a, b],计算区间内"神奇数"的个数.神奇数的定义:存在不同位置的两个数位,组成一个两位数(且不含前导0),且这个两位数为质数.比如:153,可以使用数字3和数字1组成13,13是质数,满足神奇数.同样153可以找到31和53也为质数,只要找到一个质数即满足神奇数. 输入描述: 输入为两个整数a和b,代表[a, b]区间 (1 ≤ a ≤ b ≤ 10000). 输出描述: 输出为一个整数,表示区间内满足条件的整数个数 输入例子: 11 20 输出例子: 6 1 #in

算法-计算阶乘n!末尾0的个数

算法逻辑转载自计算阶乘n!末尾0的个数: 问题描述    给定参数n(n为正整数),请计算n的阶乘n!末尾所含有"0"的个数.    例如,5!=120,其末尾所含有的"0"的个数为1:10!= 3628800,其末尾所含有的"0"的个数为2:20!= 2432902008176640000,其末尾所含有的"0"的个数为4. 计算公式    这里先给出其计算公式,后面给出推导过程.    令f(x)表示正整数x末尾所含有的&q

笔试算法题(34):从数字序列中寻找仅出现一次的数字 &amp; 最大公约数(GCD)问题

出题:给定一个数字序列,其中每个数字最多出现两次,只有一个数字仅出现了一次,如何快速找出其中仅出现了一次的数字: 分析: 由于知道一个数字异或操作它本身(X^X=0)都为0,而任何数字异或操作0都为它本身,所以当所有的数字序列都异或操作之后,所有出现两次的数字异或操作之后的结果都为0,则最后剩下的结果就是那个仅出现了一次的数字: 如果有多个数字都仅仅出现了一次,则上述的异或操作方法不再适用:如果确定只有两个数字只出现了一次,则可以利用X+Y=a和XY=b求解: 解题: 1 int findSin

计算数值区间内某个数字出现的次数

计算数值区间内某个数字 9 出现的次数 1 程序的实现 2 功能测试 3 程序的优化 4 添加调试代码 ·············· 1 程序的实现 vim 9.c gcc 9.c ./a.out 图片太大,把显示的列数修改为10. 2 功能测试 测试一个数字内部的 9 能不能准确测定. 修改: min = 9938; max = 9939; ...... ./a.out Display num:9 in 9938 and 9939. There are. |   9938   9939 Fro

Spigot 算法之一 计算调和级数的和

 我是首先在[1] 注意到 Spigot-Algorithm的,这个算法发布的相当早,见[2].  [1] 给出几个令人惊异的程序,只用很少的代码就可以计算e,pi,log(2)等常数.其中那个4行代码计算圆周率的程序被网友称作外星人写的程序,但我一直没有勇气去分析和学习它,最近终于决定学习这个 Spigot-Algorithm,先看了文献[3],明白了其基本思想,遂计划尝试编写各种计算常数的代码,并写一个系列博客.从这篇开始,我将讲述如果使用这个算法计算各种常数或者级数的和. 数列a[n]

牛牛想对一个数做若干次变换,直到这个数只剩下一位数字。 变换的规则是:将这个数变成 所有位数上的数字的乘积。比如285经过一次变换后转化成2*8*5=80. 问题是,要做多少次变换,使得这个数变成个位数。

牛牛想对一个数做若干次变换,直到这个数只剩下一位数字.变换的规则是:将这个数变成 所有位数上的数字的乘积.比如285经过一次变换后转化成2*8*5=80.问题是,要做多少次变换,使得这个数变成个位数. 输入描述: 输入一个整数.小于等于2,000,000,000. 输出描述: 输出一个整数,表示变换次数. 输入例子: 285 输出例子: 2 1 #include<stdio.h> 2 #include<stdlib.h> 3 int main() 4 { 5 int n; 6 sc