zoukankan      html  css  js  c++  java
  • 由m种数字组成的n位数有多少个

    知乎链接

    问题描述

    我和我女朋友的QQ号都是九位数字,这九个数字是有七个不同的数字组成的,我想问这种概率是多大,我们是不是特别我看缘分呢?求大神给算一下概率!

    思路

    定义问题:由7种数字组成的9位数一共有多少个?记做x,则答案为$frac{x2}{C_{10}7 imes C_{10}^{18}}$

    所以关键在于由7种数字组成的9位数一共有多少个

    from collections import Counter
    
    from scipy.special import comb as c, factorial as f
    
    """
    我和我女朋友的QQ号都是九位数字,而这九个数字完全相同只是数字顺序不同,这九个数字是有七个不同的数字组成的,我想问这种概率是多大
    """
    
    
    def split(n, m):
        """
        整数拆分,把整数n拆成m个整数之和的形式
        :param n:
        :param m:
        :return:
        """
        if m == 0: return
        a = [1] * m
        a[-1] = n - (m - 1)
        yield a
    
        def can_increase(i):
            # i是否有增长空间
            if i == m - 1: return False
            for j in range(i + 1, m):
                if a[j] - a[i] > 1:
                    return True
            return False
    
        while 1:
            # 首先找到最后一个增长点
            i = m - 1
            while i >= 0 and not can_increase(i):
                i -= 1
            # 如果没有增长点,直接退出
            if i == -1:
                break
            # 增长点增长,并且更改后续数组
            a[i] += 1
            for j in range(i + 1, m):
                a[j] = a[i]
            a[-1] = n - sum(a[:-1])
            yield a
    
    
    def g(n, m):
        """
        由m个正整数组成的n位数有多少个
        :param n:
        :param m:
        :return:
        """
        s = 0
        for i in split(n, m):
            number_left = m
            position_left = n
            now = c(10, m)
            for j in i:
                now *= number_left * c(position_left, j)
                position_left -= j
                number_left -= 1
            for j in Counter(i).values():
                now /= f(j)
            s += now
        return s
    
    
    def test():
        for i in range(1, 15):
            s = 0
            for j in range(i + 1):
                s += g(i, j)
            if s != 10 ** i:
                raise Exception("error {} {} {}".format(i, s, 10 ** i))
    
    
    def find_rule():
        ma = 30
        table = [[0] * ma for _ in range(ma)]
        for i in range(1, ma):
            for j in range(1, i + 1):
                table[i][j] = g(i, j)
        for i in range(1, ma):
            for j in range(1, i + 1):
                print("%-8d" % (table[i][j] / table[i - 1][j]) if i > 1 and table[i - 1][j] else table[i][j], end=' ')
            print()
        for i in range(1, ma):
            for j in range(1, i + 1):
                print("%-8d" % table[i][j], end=' ')
            print()
    
    
    test()
    print(g(9, 7) ** 2 / c(10, 7) / 10 ** 18)
    find_rule()
    
    

    上述程序求解复杂度较高,实际上可以找到规律。用找到的规律可以飞快解决:由m种数字组成的n位数一共有多少种这种问题。

    我找到的规律如下:
    1、对于10进制来说,由11种数字组成的n位数个数为0,因为总共就10种数字,也就是说,整个表格只有前10列不为零
    2、对于每列来说,最终都会变成等比数列,第i列的公比就是i
    3、从左上角到右下角的斜线,呈现9、8、7、6、5、4、3、2、1、0的比例

  • 相关阅读:
    简单的java socket 示例
    Java Socket编程
    session的常用方法。
    Request与session与application的区别
    百度echart使用心得,百度图表。
    SpingMVC ModelAndView, Model,Control以及参数传递
    Flume理论研究与实验
    RocketMq在SparkStreaming中的应用总结
    数据实践过程中理论总结
    flink-vs.-spark
  • 原文地址:https://www.cnblogs.com/weiyinfu/p/9385565.html
Copyright © 2011-2022 走看看