问题描述
给出一个整数序列, 去除序列中连续相邻的重复元素(只保留一个), 剩下来的数的和称之为序列的beauty. 现在给你一个长度为n的整数序列A. 问序列A的所有子序列的beauty的和是多少. 由于答案可能很大, 你只要输出答案对109+7取模的结果. Note: 在数学中,某个序列的子序列是从最初序列通过去除某些元素但不破坏余下元素的相对位置(在前或在后)而形成的新序列。 例如{1,3,2} 是{1,4,3,5,2,1}的一个子序列.
输入描述
输入有多组数据. 第一行包含一个整数T表示测试数据的组数. 对于每组数据: 第一行有一个整数n(1≤n≤105), 表示序列的大小. 接下来一行包含n个整数a1,a2,...,an, 表示序列A, (1≤ai≤109).
输出描述
对于每组数据, 输出答案对109+7取模的结果.
输入样例
3 5 1 2 3 4 5 4 1 2 1 3 5 3 3 2 1 2
输出样例
240 54 144
考虑每个数字对最终答案的贡献. 对于每个数, 我们只算它出现在连续相同元素的第一个时的贡献, 这样会使计算简便很多. 假设这个数是
a[i]
, 那么i后面的随便选有
2n−i
种. 考虑
a[i]
前面的数, 要么一个不选, 要么选择的最后一个数和
a[i]
不同, 然后就可以算出来了.
#include<stdio.h>
#include<string.h>
#include<map>
#include<algorithm>
using namespace std;
typedef long long LL;
const LL Mod = 1e9 + 7;
const int maxn = 1e5 + 10;
LL a[maxn];
LL pow2[maxn];
map<LL, LL> M;
void init()
{
pow2[0] = 1;
for(int i = 1; i < maxn; i++)
pow2[i] = pow2[i-1] * 2 % Mod;
}
int main()
{
int T, n;
scanf("%d", &T);
init();
while(T--)
{
scanf("%d", &n);
for(int i = 0; i < n; i++)
scanf("%lld", &a[i]);
M.clear();
LL ans = 0;
for(int i = 0; i < n; i++)
{
LL t = M[a[i]];
LL l = (pow2[i] - t + Mod) % Mod;
LL sum = l * pow2[n-i-1] % Mod * a[i] % Mod;
ans = (ans + sum) % Mod;
M[a[i]] = (t + pow2[i]) % Mod;
}
printf("%I64d\n", ans);
}
return 0;
}