【发布时间】:2023-03-29 22:03:02
【问题描述】:
我正在构建一个包含 Partitions 类的 C++ 库。我正在尝试就地实现共轭(如下所述),但我无法让它发挥作用。
我的班级成员是:
size_t _size;
size_t _length;
std::vector<int> _parts;
例如,整数分区[5,4,4,1]有
_size = 14 // 5 + 4 + 4 + 1
_length = 4 // 4 nonzero parts
_parts[0] = 5
_parts[1] = 4
_parts[2] = 4
_parts[3] = 1
_parts[i] = junk // i>3
如果分区是[m_1,m_2,...,m_k],那么共轭是[n_1,n_2,...,n_l] where
l = m_1 // length and the first part are switched
n_i = sum{ m_j | m_j > i}
例如,[5,4,4,1] 的共轭是[4,3,3,3,1]。另一种查看方式是将分区绘制为单位正方形的行,其中ith 行中的正方形数量为m_i。读取列的高度然后给出共轭。同样的例子,图片是
1| x
4| x x x x
4| x x x x
5| x x x x x
__________
4 3 3 3 1
数学转换为m_i = _parts[i-1] 和k = _length 的编程语法。这是共轭的错误实现:
void
Partition::conjugate() {
size_t k = _length;
_length = _parts[0];
int newPart;
for (int i=(int)_length; i>0; --i) {
newPart = 0;
for (int j=0; j<k; ++j) {
if (_parts[j] >= i) newPart++;
else break;
}
_parts[i-1] = newPart;
}
}
这在很多时候都有效,但有时它会覆盖仍然需要的部分分区。我正在寻找一种巧妙的方法来进行适当的共轭,即不创建Partition 的新实例。
另一种理解共轭的方法是认识到共轭是以下序列
k...k (k-1)...(k-1) ... 1...1
x m_k x(m_(k-1)-m_k) x(m_1 - m_2)
使用这个想法,我有以下实现可以给出正确答案:
void
Partition::conjugate() {
if (_length == _size) {
this->first();
return;
} else if (_length == 1) {
this->last();
return;
}
std::vector<int> diffs;
diffs.push_back(_parts[_length-1]);
for (size_t i=_length-1; i>0; --i)
diffs.push_back(_parts[i-1]-_parts[i]);
size_t pos = 0;
for (int i=0; i<_length; ++i) {
for (int j = diffs[i]; j>0; --j)
_parts[pos++] = (int)_length - i;
}
_length = pos;
}
但是,它使用了另一个标准向量,我试图避免。
根据 Evgeny Kluev 的回答(在下面接受),这是最终有效的代码(详情请参阅他的回答):
void
Partition::conjugate() {
if (_length == _size) {
this->first();
return;
} else if (_length == 1) {
this->last();
return;
}
int last = _parts[_length-1];
for (int i=1; i<_length; ++i)
_parts[_size-i] = _parts[i-1] - _parts[i];
size_t pos = 0;
for (int i=0; i<last; ++i)
_parts[pos++] = (int)_length;
for (int i=1; i<_length; ++i) {
for (int j = _parts[_size-_length+i]; j>0; --j)
_parts[pos++] = (int)_length - i;
}
_length = pos;
}
【问题讨论】:
-
+1 仅用于 2D 图表。我一直在挠头,直到一切都到位。不知道您想要什么是否可能(还没有真正考虑过),但绝对有资格作为一个有趣的问题。
-
你能给出一个数据集,其中仍然需要的分区的某些部分被覆盖了吗?
-
@KhouriGiordano 上面的例子打破了它,
[5,4,4,1]。 -
如果向量 u 的元素是按降序排列的正整数,我们会说它在空间 V 中。 u 在 V 中有一个唯一的共轭,在 V 中也称为 w。因为共轭在这个空间中是唯一的,所以不存在使 conjugate(u') = w 的中间向量 u'。这意味着依赖于修改 u 来找到 w 的策略都将失败。但是,它确实让我们了解到,也许您可以在重新排列 u 内的值的位置时存储一些信息(将 u 移到 V 之外并进入所有正整数向量的空间)。不过,我不知道有什么明显的方法可以利用它。
-
@Welbog 您关于解决方案不存在的论点对我来说没有任何意义。此外,可以修改 stdvector,使其在中间的某个阶段不再是整数分区。
标签: c++ algorithm math integer-partition