所有可能的比赛得分的总和

时间:2017-06-09 17:48:14

标签: c++ algorithm

我正在研究解决方案无法理解的问题。我提出了自己的解决方案,但是没有接受:

N + 1个数字从A0到AN顺序出现(一次一个)。每个数字都可以放在最后一个序列的两侧。此时的分数将是该数字与其邻居的乘积,例如:A0.A1.A2或A2.A0.A1(A2可以放置在A0.A1的任一侧,因此分数可以是A1.A2或A2。 A0;在A2出现之前也可能存在A1.A0)。我们需要在所有可能的组合中总结所有可能的分数;即第一序列在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 个答案:

答案 0 :(得分:1)

说明

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

  1. sum表示元素0..i-1
  2. 的所有排列的总分
  3. extra表示元素0..i-1的所有排列的两个边元素的总和
  4. 另请注意,元素0..i。

    pow[i]=2^i个排列

    在开始时,唯一的排列是[A0],其总和为0,并且左边缘和右边缘的A0的总边缘为A.A0。

    在迭代i中,我们通过考虑所有那些Ai在左边的那些,以及所有那些Ai在右边的东西,将排列的数量加倍。因此,这些排列的内部得分为2*sum,考虑边缘样本的额外得分为Ai*extra

    同样extra需要为所有2^i排列增加Ai,因为它在每个新排列中位于左侧或右侧。

    实施例

    考虑[A0,A1,A2]。

    有4种可能的方法来建立序列:

    1. 右/右A0,A1,A2得分= A0.A1 + A1.A2
    2. 右/左A2,A0,A1得分= A0.A1 + A2.A0
    3. 左/右A1,A0,A2得分= A0.A1 + A2.A0
    4. 左/左A2,A1,A0得分= A0.A1 + A2.A1
    5. 总分为4A0.A1 + 2A1.A2 + 2A2.A0