HDU 5496 - BestCoder Round #58 - Beauty of Sequence
题目链接 : http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=637&pid=1002
思路 :
考虑这个序列当前的第i个数能有几种组合方法, 前面有2^(i-1)种, 后面有有2^(n-i)种, 本来答案是a[i] * 2^(n-1), 但要求对于某种排列存在相邻且相等的数是不计入答案的
例如 第二组样例 1 2 1 3, 1 1 3中1重复故要减去一个1
可见, 只有前一个数和a[i]相等时, a[i]就不能计入了, 而后面和a[i]相等便可以计入(后面和a[i]相等时, 可以看作约去后面的值, 这一种方法对a[i]这个值依然有1个贡献)
所以关键就是得到第i个数, 前面有几种以a[i]结尾的方法, 设为k, 这是要减去的方法数, a[i]的贡献就是a[i] * 2^(n-i) *[2^(n-i) - k]
方法 :
2的幂次预处理到10^5
对于得到k, 可以用map + 前缀和的形式记录, 例如当前位置i, 第一次得到一个a[i], 那么以这个数结尾有2^(i-1)种方法, 第二次在j位置得到了a[j] = a[i]
那么以a[i]结尾的就变成了2^(i-1) + 2^(j-1)种
比赛的时候没想到用map记录, n^2完全不敢写, 太弱了= =
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <map> 5 6 using namespace std; 7 8 typedef long long LL; 9 10 const int MAXN = 1e5+10; 11 const int MOD = 1e9+7; 12 13 map<int, LL> r; 14 int a[MAXN]; 15 int f[MAXN]; 16 int Pow[MAXN]; 17 18 void Pre() 19 { 20 Pow[0] = 1; 21 for(int i = 1; i < MAXN; i++) { 22 Pow[i] = (Pow[i-1] << 1) % MOD; 23 } 24 } 25 26 void Init() 27 { 28 r.clear(); 29 } 30 31 int main() 32 { 33 Pre(); 34 35 int t; 36 int n; 37 38 scanf("%d", &t); 39 while(t--) { 40 Init(); 41 scanf("%d", &n); 42 for(int i = 0; i < n; i++) { 43 scanf("%d", &a[i]); 44 f[i] = (LL)Pow[n-i-1] * (Pow[i] - r[a[i]] + MOD) % MOD; 45 r[a[i]] += Pow[i]; 46 r[a[i]] %= MOD; 47 } 48 LL ans = 0; 49 for(int i = 0; i < n; i++) { 50 ans += (LL)a[i] * f[i]; 51 ans %= MOD; 52 } 53 printf("%I64d\n", ans); 54 } 55 56 return 0; 57 }