思路参考自: http://blog.csdn.net/doris1104/article/details/51126910 thanks
找规律发现 最后一个球和前面球相邻的次数(满足 左边大于右边的) 和 2^ 两个球的间距 有关
----->越靠近相邻次数越多。
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 5 #include<string> 6 #include<algorithm> 7 #include<set> 8 #include<map> 9 #include<vector> 10 #include<stack> 11 #include<queue> 12 #include<cmath> 13 14 #include<iostream> 15 using namespace std; 16 17 typedef long long ll; 18 const int mod = 1000000007; 19 ll ans[100005],two[100005],num[100005],sum[100005]; 20 21 /* 22 num[a] : 用来保存已经出现 a 需要减去的次数 23 num[tmp] = (num[tmp] + two[i-1]) % mod; 越近相邻次数越多,如果两数相同,减去的也越多 24 25 *sum[i] = (sum[i-1] + two[i]) % mod; 26 情况和 27 28 ans[i] = (2*ans[i-1] + sum[i - 2] - num[tmp] + mod) % mod; 29 之前的情况和 加上这个的 30 两端都可插入 31 之前情况*2 32 */ 33 34 void init(){ 35 two[0] = two[1] = 1; 36 for(int i = 2 ; i < 100005 ; i ++){ 37 two[i] = (2*two[i-1])%mod; 38 } 39 sum[0] = 1; 40 for(int i = 1 ; i < 100005 ; i ++){ 41 sum[i] = (sum[i-1] + two[i]) % mod; 42 } 43 44 } 45 46 int main(){ 47 48 int T; 49 init(); 50 scanf("%d",&T); 51 while(T--){ 52 int n; 53 scanf("%d",&n); 54 memset(ans,0,sizeof(ans)); 55 memset(num,0,sizeof(num)); 56 for(int i = 1 ,tmp ; i <= n ; i ++){ 57 scanf("%d",&tmp); 58 ans[i] = (2*ans[i-1] + sum[i - 2] - num[tmp] + mod) % mod; 59 num[tmp] = (num[tmp] + two[i-1]) % mod; 60 } 61 printf("%lld\n",(ans[n]*2)%mod); 62 } 63 64 return 0; 65 }
时间: 2024-10-01 03:35:39