美文网首页
多元线性方程整数解的计数

多元线性方程整数解的计数

作者: Lysias | 来源:发表于2020-01-25 16:51 被阅读0次

    多元线性方程整数解的计数

    [TOC]

    问题描述

    统计
    S=a_0x_0+a_1x_1+...+a_nx_n(a>0)
    的非负整数解的个数。列出这些解。

    枚举

    静态地看,x_i的范围容易确定,x_i\in[0,\frac{S}{a_i}]。各个范围的笛卡尔积X是答案的范围,其中的元素记为x。将每个x带入方程验证,即可筛选出解。

    from itertools import product
    def cc(s, a):
        def p(x):
            return sum([x * a for x, a in zip(x, a)])
        
        return [x for x in product(*[range(s // ai + 1) for ai in a]) if p(x) == s]
    

    递归

    如果将决定x中每个x_i看作一个动态的过程,则已决定的x_i对未决定的x_i的范围有影响。我们可以沿着两个方向减小问题的规模,分别是

    • 减小变量的个数
    • 减小S
    def cr(s, a):
        def r(s, a, x):
            if s == 0:
                xs.append(tuple(x))
            elif s > 0 and len(a) != 0:
                x = list(x)
                r(s, a[:-1], x)        # 减小变量个数
                
                x = list(x)
                x[len(a) - 1] += 1
                r(s - a[-1], a, x)     # 减小S
        
        xs = []
        r(s, a, [0] * len(a))
        return xs
    

    代码中x就是X中的某个x.

    对比

    将递归树叶子节点的个数作为递归的复杂度,与枚举法的X中元素个数做对比,发现枚举空间的大小大约是递归空间大小的40倍。运行时间的比值也接近40。

    附录

    jupyter notebook 完整实验代码:

    from itertools import *
    
    l = 0
    
    def cc(s, a):
        global l
        def p(x):
            return sum([x * a for x, a in zip(x, a)])
        
        l = len([x for x in product(*[range(s // ai + 1) for ai in a])])
        return [x for x in product(*[range(s // ai + 1) for ai in a]) if p(x) == s]
    
    x1 = cc(100, [1, 5, 10, 25, 50])
    
    cnt = 0
    
    def cr(s, a):
        
        def r(s, a, x):
            global cnt
            if s == 0:
                xs.append(tuple(x))
                cnt += 1
            elif s > 0 and len(a) != 0:
                x = list(x)
                r(s, a[:-1], x)
                
                x = list(x)
                x[len(a) - 1] += 1
                r(s - a[-1], a, x)
            else:
                cnt += 1
        
        xs = []
        r(s, a, [0] * len(a))
        return xs
    
    x2 = cr(100, [1, 5, 10, 25, 50])
    
    set(x1) == set(x2)
    
    x1 == x2
    
    l / cnt
    
    %timeit cc(100, [1, 5, 10, 25, 50])
    
    %timeit cr(100, [1, 5, 10, 25, 50])
    

    相关文章

      网友评论

          本文标题:多元线性方程整数解的计数

          本文链接:https://www.haomeiwen.com/subject/hwurthtx.html