0219 成本偏斜编码
* * * *
拉格朗日计划
* * * *
成本偏斜编码

设A和B均为比特串(由0和1组成的序列)。

若从B的左端取和A的长度相等的比特位所得的子串恰好等于A,就称A为B的前缀。

例如,00110是001101001的前缀,但不是00111或100110的前缀。

n元无前缀编码是指由n个不同的比特串组成的集合,这些比特串间两两都不互为前缀。

例如,{0000,0001,001,01,10,11}就是一种六元无前缀编码。

现假定传输比特位0的花费是一分钱,而传输比特位1的花费是四分钱。

那么,上述六元无前缀编码的总花费是35分钱,恰是总花费最低的六元无前缀编码。

Cost(n)总花费最低的n元无前缀编码的费用,例如Cost(6)=35

Cost(109)

本题难度:



解答

基本策略与霍夫曼编码一致。

考虑这样一种二叉树,根节点的值为空串,表示比特串的起始,其它所有节点的值均为0或1,可以规定若当前节点是其父节点的左子节点,则其值为0,否则值为1。

每一条从根节点到每一个叶节点的路径都唯一对应一个比特串,n元无前缀编码就可以按此方式形成一颗有n个叶节点的二叉树,例如题面中的六元无前缀编码对应二叉树:



为叙述方便,以下行文中不区分n元无前缀编码及其所对应的二叉树。

Tn={a1,,an}表示一个n元无前缀编码,并用|ak|表示编码ak的花费。

TnTn中的编码的最大花费,记Tn1Tn中的编码的总花费。

c(i)为最大花费不超过i的情况下的最多的编码数,即 c(i)=max{n:Tni}.Tc(i)为满足上述要求、且总费用最低的树,注意由此定义可知这样的树是唯一的。

c(i)而言,有初值c(0)=c(1)=c(2)=c(3)=1,以及递推式 c(i)=c(i1)+c(i4). 这是因为由最大性可以分别在Tc(i1)的所有编码前添加一位0Tc(i4)的所有编码前添加一位1,再将两者合并来得到Tc(i)

再令 s(i)=Tc(i)1, 则有初值s(0)=s(1)=s(2)=s(3)=0(注意一元无前缀编码中总费用最低的是空树),再由c(i)的递推构造可得 s(i)=s(i1)+s(i4)+c(i1)+4c(i4). 设m是满足c(m)109中最大的数,要计算Cost(109),还需在Tc(m)中再添加109c(m)条编码。

Tc(m)叶节点数的最大性可知只能扩展那些费用不小于m3的叶节点。

在这样的叶节点下添加两个子节点,相当于在Tc(m)1中先移除mkk=0,1,2,3),再添加mk+1mk+4,因此总费用增加m+5k

为使扩展后的总费用最低,应按k的值从大到小开始扩展,实现中经计算可以验证费用为m3的节点数超过109c(m)个,因此只需扩展这一种类型的节点即可。

最后结果为 s(m)+(109c(m))(m+2)=64564225042.
target=10**9
c=[1,1,1,1]
s=[0,0,0,0]
while c[-1]<=target:
    s.append(s[-1]+s[-4]+c[-1]+4*c[-4])
    c.append(c[-1]+c[-4])

print (target-c[-2])*len(c)+s[-2]