所有可能的游戏分数的总和

sum of all possible game scores

本文关键字:游戏 有可能      更新时间:2023-10-16

我正在研究一个解决方案无法理解的问题。我想出了自己的解决方案,但这不被接受:

N+1 个数字从 A0 到 AN 依次出现(一次一个)。每个数字可以放置在最后一个序列的两侧。此时的分数将是该数字与其邻居的乘积,例如:A0。回答 1.A2 或 A2。回答 0.A1(A2 可以放置在 A0 的两侧。A1,所以分数可能是A1。A2 或 A2。A0;也可能有A1的可能性。A0 出现之前的 A2)。我们需要总结所有可能组合中所有可能的分数;即第一个序列对 N+1 个数字的分数总和,然后对其他序列的总和,依此类推,最后是所有这些总和的总和。

以下是被发现可以接受的逻辑:

int pwr[0] = 1;
for (int i = 1; i < 100000; i++)
pwr[i] = (pwr[i - 1] << 1) % MOD;
extra = A0 * 2;
sum = 0;
for (int i = 1; i <= N; i++){
Ai = scan();
sum = (sum * 2 + Ai * extra) % MOD; //Mod is a scaling factor
extra = (extra + pwr[i] * Ai) % MOD;
}

有人可以解释一下这是如何工作的吗?

这是我对同一问题的逻辑(解决方案),但没有接受:

#include <iostream>
#include <cmath>
int main()
{
int T;
std::cin>>T;
long long int output[T];
for (int i = 0; i < T; ++i)
{
int N;
std::cin>>N;
long long int inp[N+1];
for (int j = 0; j <= N; ++j)
{
std::cin>>inp[j];
}
long long int tot = 0;
for (int j = 0; j < N; ++j)
{
for (int k = j+1; k <= N; ++k)
{
tot += (inp[j] * inp[k] * pow(2,N-k+1));
}
}
long long int num = pow(10,9) + 7;
output[i] = tot % num;
}
for (int i = 0; i < T; ++i)
{
std::cout<<output[i]<<std::endl;
}
return 0;
} 

解释

在循环的每次迭代开始时,我相信:

  1. sum表示元素 0..i-1 的所有排列的总分
  2. extra表示元素 0..i-1 的所有排列的两个边元素的总和

另请注意,元素 0..i 有pow[i]=2^i排列。

开始时,唯一的排列是 [A0],其总和为 0,总边缘为 2.A0,因为 A0 同时位于左边缘和右边缘。

在迭代 i 中,我们通过考虑所有 Ai 在左边的排列和所有 Ai 在右边的排列来加倍排列的数量。 因此,这些排列的内部分数是2*sum的,而考虑边缘样本的额外分数是Ai*extra

此外,对于所有2^i排列,extra需要增加 Ai,因为它在每个新排列中要么在左侧,要么在右侧。

考虑 [A0,A1,A2]。

有4 种可能的方法可以构建序列:

  1. /右 A0,A1,A2 分数 = A0。A1+A1.答2
  2. 右/左 A2,A0,A1 分数 = A0。A1+A2。答0
  3. 左/右 A1,A0,A2 分数 = A0。A1+A2。答0
  4. /左 A2,A1,A0 分数 = A0。A1+A2。答1

总分是4A0。A1+2A1.A2+2A2。答0