给定一个序列(d1,d2,...,dn),我想评估所有i!= j的乘积(1-Dij),其中Dij = 1,如果di = dj,则为0。
我的代码只检查了Dij
prod = 1;
for (int i=1; i<n; ++i) {
for (int j=i; j<=n; ++j) {
prod *= (1 - Dij);
}
}
我知道当我得到Dij = 1时我可以停止,但我想要做的是获得Dij的最小表达来检查。这样我有一个表达式然后我可以使用差异序列并对其进行评估。所以我知道我可以i<j
代替i != j
。所以我想扩展这个产品并得到类似的东西n = 3:
(1 - D12) (1 - D13) (1 - D23) = 1 - D12 - D13 - D23 + D12*D13 + D12*D23 + D13*D23 - D12*D13*D23
但我能做的更多。该表达式实际上总是等于
1 - D12 - D13 - D23 + 3 * D12*D13 - D12*D13*D23
我的问题是:
为什么D12 * D13 = D12 * D23?这总是正确的(意味着d序列是什么并不重要),但我真的不明白为什么因为在我看来这意味着D13 = D23并不总是正确的(这取决于d序列) 。这是有助于使表达更小的关系。
如何找到这样的所有关系并获得最小的表达式?上面的表达是否最小?我甚至都不知道。
答案 0 :(得分:3)
您正在尝试确定D是否包含任何重复项。最终,这需要您将每个条目相互比较,这只是枚举两个元素的所有独特组合。最终成为N*(N-1)/2
。您可以通过先排序D然后搜索重复的相邻对(O(N*log(N)
)来做得更好,或者,假设您坚持有界的整数范围,您可以使用位向量将其减少到线性时间,或者如果你喜欢冒险,那就是基数。
答案 1 :(得分:2)
我可以为你回答1。考虑这两种情况:
案例1:D13 = D23
您可以在这里乘以D12
两侧以获得D12 * D13 = D12 * D23
。
案例2:D13 != D23
这意味着d1 = d3
XOR d2 = d3
,但不是。因此,我们知道d1 != d2
。这意味着D12 = 0
。因此
D12 * D13 = 0 * D13 = 0 = 0 * D23 = D12 * D23
当您认为这意味着D13 = D23
时,您的逻辑问题在于您不能除以0
,而D12
可能是0
(总是在第二次出现)案件)。
你的第二个问题很有意思,我不知道答案,但这里有一些可能有用的观察结果。
连续绘制数字1, 2, ..., n
:
1 2 3 ... n
给定表达式D_(i1,j1) * D_(i2,j2) * ... * D_(ik,jk)
,从i1 to j1
和i2 to j2
创建一个弧,依此类推。这会将该行转换为图形(顶点是数字,边是这些弧)。
该图表的每个连接组件代表数字1, 2, ..., n
的一个子集,从整体上看,它为{1, 2, ..., n}
D12 * D23 = D12 * D13
---------
| |
1 -- 2 -- 3 = 1 -- 2 3
提供了set partition。
事实:具有相同对应设置分区的任何两个术语都是相同的。
示例:
D12 * D13 * D23
---------
| |
1 -- 2 -- 3
有时这个事实意味着程度是相同的,就像上面的情况一样,有时程度会降低,如
\prod_{i<j} ( 1 - Dij ) = \sum_{P set partition of \{1,2,...,n\}} c_P * m_P
结果是,现在您可以将产品(1 - Dij)表示为设置分区的总和:
mP = mP1 * mP2 * ... * mPk
其中单项术语由
给出P = P1 union P2 union ... union Pk
Pi = { a < b < c < ... < z }
和m_Pi = Dab * Dac * ... * Daz
时
c_P = \prod (#P1)! (#P2)! ... (#Pn)!
最后,系数项只是
{{1}}
解决了这个问题后,我现在确定这属于http://math.stackexchange.com,而不是在这里。
答案 2 :(得分:0)
我没有按照数学计算,但是如果你知道di的大小是有限的,你不会使用散列表编码,或者甚至可能是稀疏的位数组?只需遍历列表,在对应于di值的位置填入数据结构“1” - 如果已经为1,则返回0.如果完成(n步),则返回1.应该是O (n)的