CF - 810C. Do you want a date? - 数学+排序+前缀和思维+快速幂取模

28 篇文章 0 订阅
26 篇文章 0 订阅

1.题目描述:

C. Do you want a date?
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Leha decided to move to a quiet town Vičkopolis, because he was tired by living in Bankopolis. Upon arrival he immediately began to expand his network of hacked computers. During the week Leha managed to get access to n computers throughout the town. Incidentally all the computers, which were hacked by Leha, lie on the same straight line, due to the reason that there is the only one straight street in Vičkopolis.

Let's denote the coordinate system on this street. Besides let's number all the hacked computers with integers from 1 to n. So the i-th hacked computer is located at the point xi. Moreover the coordinates of all computers are distinct.

Leha is determined to have a little rest after a hard week. Therefore he is going to invite his friend Noora to a restaurant. However the girl agrees to go on a date with the only one condition: Leha have to solve a simple task.

Leha should calculate a sum of F(a) for all a, where a is a non-empty subset of the set, that consists of all hacked computers. Formally, let's denote A the set of all integers from 1 to n. Noora asks the hacker to find value of the expression . Here F(a) is calculated as the maximum among the distances between all pairs of computers from the set a. Formally, . Since the required sum can be quite large Noora asks to find it modulo 109 + 7.

Though, Leha is too tired. Consequently he is not able to solve this task. Help the hacker to attend a date.

Input

The first line contains one integer n (1 ≤ n ≤ 3·105) denoting the number of hacked computers.

The second line contains n integers x1, x2, ..., xn (1 ≤ xi ≤ 109) denoting the coordinates of hacked computers. It is guaranteed that all xiare distinct.

Output

Print a single integer — the required sum modulo 109 + 7.

Examples
input
2
4 7
output
3
input
3
4 3 1
output
9
Note

There are three non-empty subsets in the first sample test: and . The first and the second subset increase the sum by 0and the third subset increases the sum by 7 - 4 = 3. In total the answer is 0 + 0 + 3 = 3.

There are seven non-empty subsets in the second sample test. Among them only the following subsets increase the answer: . In total the sum is (4 - 3) + (4 - 1) + (3 - 1) + (4 - 1) = 9.


2.题意概述:

定义一个集合内的F值是所有子集(包括自身)里面最大元素与最小元素的差,给你n个元素a[1...n],问它所构成的集合的F值是多少?

3.解题思路:

首先得想到排序,这样对于元素就有了单调性,那么我们枚举i从1到n表示某个集合包含a[i](显然i就是集合的最小元素), 再枚举一个j从第一个大于i的数枚举到n表示某个集合包含a[j](显然最大的元素就是a[j]),那么它们的F值就是a[j]-a[i],容易证明这样枚举i,j就是这个集合的一个划分(所有可能情况都囊括在内),因为如果a[j]小于等于a[i]这样的子集F值是0,对总体F值根本无贡献。下面考虑对于每一个i和j它们的子集(包含自身)个数,假设里面元素除去i和j还有i+1, i+2, ... j,那么选法依次有选0, 1, ..., j - i - 1个元素构成集合,因此就是个子集,,,那么对答案的贡献就是(a[j]-a[i])*,指数运算可以考虑快速幂取模运算来加速,但是这样复杂度还是n^2的,果然还是T在第八个了。

进一步思考,对于每个i, j,取值可能有,第一种前面系数是(a[2]-a[1]+a[3]-a[2]+...+a[n]-a[n-1])=a[n]-a[1],同理可以发现第二种是a[n]+a[n-1]-a[1]-a[2]......,那么就推出来了:,因此可以用前缀和和后缀和来维护一下,每次计算就O(1)的,O(n)地枚举i答案就出来了,还有个坑点在于取模运算的规则。

4.AC代码:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define maxn 300010
#define lson root << 1
#define rson root << 1 | 1
#define lent (t[root].r - t[root].l + 1)
#define lenl (t[lson].r - t[lson].l + 1)
#define lenr (t[rson].r - t[rson].l + 1)
#define N 1111
#define eps 1e-6
#define pi acos(-1.0)
#define e exp(1.0)
using namespace std;
const int mod = 1e9 + 7;
typedef long long ll;
typedef unsigned long long ull;
int a[maxn];
ll sum1[maxn], sum2[maxn];
ll quickmod(ll a, ll b, ll m)
{
	ll ans = 1;
	while (b)//用一个循环从右到左便利b的所有二进制位
	{
		if (b & 1)//判断此时b[i]的二进制位是否为1
		{
			ans = (ans*a) % m;//乘到结果上,这里a是a^(2^i)%m
			b--;//把该为变0
		}
		b /= 2;
		a = a*a%m;
	}
	return ans;
}
int main()
{
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
	long _begin_time = clock();
#endif
	int n;
	while (~scanf("%d", &n))
	{
		for (int i = 1; i <= n; i++)
			scanf("%d", &a[i]);
		sort(a + 1, a + n + 1);
		sum1[0] = sum2[n + 1] = 0;
		for (int i = 1; i <= n; i++)
			sum1[i] = sum1[i - 1] + a[i];
		for (int i = n; i > 0; i--)
			sum2[i] = sum2[i + 1] + a[i];
		ll ans = 0;
		for (int i = 1; i < n; i++)
		{
			ll tmp = (-sum1[i] + sum2[n - i + 1]) % mod;
			ans = (ans % mod + tmp * quickmod(2, i - 1, mod)) % mod;
		}
		printf("%I64d\n", ans);
	}
#ifndef ONLINE_JUDGE
	long _end_time = clock();
	printf("time = %ld ms.", _end_time - _begin_time);
#endif
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值