Time Limit: 1 sec Source Limit: 50000 Bytes
Churu is working as a data scientist in Coderpur. He works on a lot of data on the daily basis. One day, he found an interesting problem, which was very easy to solve for small data but was getting more complex with increasing number of data points. So, Churu needs your help in solving this problem.
Given a set S of N non-negative integers (Some integers might occur more than once in the set), find out the value of SETDIFF(S).
Where max(s) represents the maximum value in set s whereas min(s) represents the minimum value in the set s.
As value of SETDIFF(S) can be very large, print it modulo (109 + 7) .
There might be repeated values in the set. For set S = {1,2,2}, consider that first 2 is not same as the second 2 and there will be two different subsets {1,2}. See last sample case for the more clarifications.
Input
First line of input contains an integer T denoting number of test cases.
For each test case, first line will contain an integer N denoting number of elements in set S.
Next line contains N space separated integers denoting the set S.
Output
For each test case, print a single integer representing the answer of that test case.
Note
Two subsets will be called different if there exists an index i such that S[i] occurs in one of the subset and not in another.
Constraints
Subtask #1: 20 points
1 ≤ T ≤ 5, 1 ≤ N ≤ 1000, 0 ≤ value in set ≤ 109
Subtask #2: 25 points
1 ≤ T ≤ 5, 1 ≤ N ≤ 105, 0 ≤ value in set ≤ 1000
Subtask #3: 55 points
1 ≤ T ≤ 5, 1 ≤ N ≤ 105, 0 ≤ value in set ≤ 109
Example
Input:
4
2
1 2
3
1 2 3
4
1 2 3 4
3
1 2 2
Output:
1
6
23
3
Explanation
For first case answer will be 2-1 = 1.
For the second case:
Subset = {1}, max(s)-min(s) = 0.
Subset = {2}, max(s)-min(s) = 0.
Subset = {3}, max(s)-min(s) = 0.
Subset = {1,2}, max(s)-min(s) = 1.
Subset = {2,3}, max(s)-min(s) = 1.
Subset = {1,3}, max(s)-min(s) = 2.
Subset = {1,2,3}, max(s)-min(s) = 2.
So the output will be 1+1+2+2 = 6.
In the last case, there are three subsets, {1,2}, {1,2} and {1,2,2} having max(s) - min(s) = 1 for each.
题目大意:给定一个含N个非负整数的集合S(集合中元素可重复),求SETDIFF(S)的值。
需要注意的是两个子集当存在至少一个下标i,是的S[i]在其中一个子集中,而不在另一个子集中,另外取余也需要注意
题目思路:找规律。
题目链接:Set Difference
以下是代码:
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <string>
#include <cstring>
#define MOD 1000000007
using namespace std;
long long pownum[100100];
int n;
int num[100100];
void solve()
{
pownum[0] = 1;
for (int i = 1; i <=100000; i++)
{
pownum[i] = (pownum[i - 1] * 2) % MOD;
}
}
int main(){
int t;
cin >> t;
solve();
while(t--)
{
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> num[i];
}
sort(num,num + n);
long long sum1 = 0,sum2 = 0;
//这是未优化前的代码,还需要排列组合函数。外面i的循环代表从S中取几个数,可以发现随着i的变化num[j] * C(n - j - 1, i + 1)中只有i + 1在变化,于是可以想到二项式定理,去掉外面那层循环。
/*for (int i = 0; i <= n - 2; i++) { for (int j = 0; j < n; j++) { if (n - j - 1 > 0) { sum1 += num[j] * C(n - j - 1, i + 1); } if (j > 0) { sum2 += num[j] * C(j,i + 1); } } }*/
//优化过后
for (int j = 0; j < n; j++)
{
sum1 =(sum1+ num[j] * pownum[n-j-1] )% MOD;
sum2 =( num[j] * pownum[j] +sum2)% MOD;
}
cout << ((MOD+sum2 - sum1) % MOD) << endl;
}
return 0;
}