免责声明:此问题涉及相应社论的内容。因此,如果你想自己尝试这个问题,我不鼓励你阅读这篇文章。此外,我的问题遗漏了社论中提到的一些细节,所以请在阅读我的问题时参考社论。
另外,请记住,我不打算为HackerRank做广告;此外,我不会因编辑,问题描述或任何其他被HackerRank或附属方侵犯版权的材料而受到赞誉。
实际问题:
我正在尝试理解这篇problem的社论。具体来说,我感到困惑的部分是以下代码:
...
for(int i=1;i<=k;i++) {
for(int j=0;j<8192;j++) {
mem[flag][j] = (mem[flag^1][j]*(1+(a[v[i-1]])/2))%mod + (mem[flag^1][j^v[i-1]]*((a[v[i-1]]+1)/2))%mod;
if(mem[flag][j]>=mod)
mem[flag][j]%=mod;
}
flag = flag^1;
}
社论指出“......使用这个属性,我们可以编写一个O(N)
动态编程解决方案,其8192
常数因子,dp[i][j]
将存储可以的子集数用第一个元素形成,使得子集中元素的xor和为j
。“
从代码中可以看出mem
基本上是dp
,除了我无法理解flag
的功能 - 是什么 flag
?另外,我得到1 + (a[v[i - 1]])/2
对应于[0,a [v [i - 1]]]中的平均数,而(a[v[i - 1]] + 1) / 2
对应于同一时间间隔内的赔率数,但我不知道不知道它与一切有什么联系。
提前感谢您的努力。
答案 0 :(得分:5)
这是一种在使用动态编程时减少内存使用的标准方法。
这个想法是DP阵列的每一行通常只依赖于前一行。在这种情况下,不是存储整个2d DP [i] [j]数组,而是只使用数组的2行。
换句话说,如果i是偶数,则DP [i] [j]存储在mem [0] [j]中,如果i是奇数,则存储在mem [1] [j]中。 mem数组被重复使用多次,并且在每次迭代后保存完整DP阵列的最新两行。
假设我们有5个特定值的副本v。有1 + 5/2种方法使xor为0(取0或4个副本)。有(1 + 5)/ 2种方法制作vor(取1,3或5份)。
因此,要创建新值j,我们可以从j开始并添加0或4个v副本,或者从j ^ v开始并添加1,3或5个副本。
答案 1 :(得分:0)
flag用于减少过多的内存使用,因为dp仅取决于先前的状态。
为什么循环[0,8192]:正如问题[a] i == 4500所给,那么当我们对两个数进行“或”运算时,它将达到8192。 Xor属性..