D. Moving Dots

D. Moving Dots

We play a game with n dots on a number line.

The initial coordinate of the i-th dot is xi. These coordinates are distinct. Every dot starts moving simultaneously with the same constant speed.

Each dot moves in the direction of the closest dot (different from itself) until it meets another dot. In the case of a tie, it goes to the left. Two dots meet if they are in the same coordinate, after that, they stop moving.

After enough time, every dot stops moving. The result of a game is the number of distinct coordinates where the dots stop.

Because this game is too easy, calculate the sum of results when we play the game for every subset of the given n dots that has at least two dots. As the result can be very large, print the sum modulo 109+7.

Input

The first line contains one integer n (2n3000).

The next line contains n integers x1,x2,,xn (1x1<x2<<xn109), where xi represents the initial coordinate of i-th dot.

Output

Print the sum of results modulo 109+7.

Examples

input

4
1 2 4 6

output

11

input

5
1 3 5 11 15

output

30

Note

In the first example, for a subset of size 2, two dots move toward each other, so there is 1 coordinate where the dots stop.

For a subset of size 3, the first dot and third dot move toward the second dot, so there is 1 coordinate where the dots stop no matter the direction where the second dot moves.

For [1,2,4,6], the first and second dots move toward each other. For the third dot, initially, the second dot and the fourth dot are the closest dots. Since it is a tie, the third dot moves left. The fourth dot also moves left. So there is 1 coordinate where the dots stop, which is 1.5.

Because there are 6 subsets of size 2, 4 subsets of size 3 and one subset of size 4, the answer is 61+41+1=11.

In the second example, for a subset of size 5 (when there are dots at 1, 3, 5, 11, 15), dots at 1 and 11 will move right and dots at 3, 5, 15 will move left. Dots at 1, 3, 5 will eventually meet at 2, and dots at 11 and 15 will meet at 13, so there are 2 coordinates where the dots stop.

 

解题思路

  题目看了半天都没看懂。大概就是每次从点集里面选择一个子集(至少要有两个元素),然后每个点都以相同的速度向距离它最近的点移动(如果距离两边的点都相同则统一向左移动),如果碰到其他点则停止移动,最后数轴上不动的点有为x个。问在所有的子集中,x的总和是多少。

  这题最关键的地方是要想到数轴最终留下的点必然是由子集序列中相邻的两个点相遇所形成的。因此可以枚举点对(xi,xj),统计每个点对能够贡献的答案是多少。如果想让xixj相遇成为最后留下的点,那么首先在xi<xk<xj范围内的点不能选。同时,我们还要保证xi向左移动xj向右移动,记d=xjxi,那么xidxk<xixj<xkxj+d1内的点不能选。假设通过二分出来xi左边有l个点可以选,xj右边有r个点可以选,那么最终留下由(xi,xj)形成的点的集合个数就是2l+r

  AC代码如下,时间复杂度为O(n2logn)

复制代码
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long LL;
 5 
 6 const int N = 3010, mod = 1e9 + 7;
 7 
 8 int n;
 9 int a[N];
10 
11 int qmi(int a, int k) {
12     int ret = 1;
13     while (k) {
14         if (k & 1) ret = 1ll * ret * a % mod;
15         a = 1ll * a * a % mod;
16         k >>= 1;
17     }
18     return ret;
19 }
20 
21 int find(int x) {   // 二分找到大于等于x的最小下标
22     int l = 1, r = n + 1;
23     while (l < r) {
24         int mid = l + r >> 1;
25         if (a[mid] >= x) r = mid;
26         else l = mid + 1;
27     }
28     return l;
29 }
30 
31 int main() {
32     scanf("%d", &n);
33     for (int i = 1; i <= n; i++) {
34         scanf("%d", a + i);
35     }
36     a[n + 1] = 2e9; // 加个哨兵,保证可以二分出结果
37     int ret = 0;
38     for (int i = 1; i <= n; i++) {
39         for (int j = i + 1; j <= n; j++) {
40             int d = a[j] - a[i];
41             int l = find(a[i] - d) - 1; // 左边可以选的点数
42             int r = n - find(a[j] + d) + 1; // 右边可以选的点数
43             ret = (ret + qmi(2, l + r)) % mod;  // 快速幂求2^{l+r}
44         }
45     }
46     printf("%d", ret);
47     
48     return 0;
49 }
复制代码

 

参考资料

  Codeforces Round #851 (Div. 2) Editorial:https://codeforces.com/blog/entry/112584

posted @   onlyblues  阅读(54)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
Web Analytics
点击右上角即可分享
微信分享提示