【组合 数学】codeforces C. Do you want a date?
2024-08-30 17:22:03
codeforces.com/contest/810/problem/C
【题意】
给定一个集合A,求
,
输入:
【思路】
基数为n的集合有2^n-1个非空子集。
首先n个数要从小到大排序,枚举最后的集合中最大和最小的元素是a[i]和a[j](i< j);
则f值是a[j]-a[i]的集合有2^(j-i-1)个; 然后答案+=(a[j]−a[i])*2^(j-i-1);
这样时间复杂度是O(n^2)。
我们可以把各项组合一下,把2^i提取出来。
比如考虑系数为
2^1的
必然是
a[3]-a[1]
a[4]-a[2]
a[5]-a[3]
…
a[n]-a[n-2]
=sum[n]-sum[i+1]-sum[n-i-1];
sum[i]是a[i]的前缀和。
这样对于[0,n-2]枚举2^i,时间复杂度是O(n),加上排序,总的时间复杂度是O(nlogn)
【注意】
sum[i]是取余后的结果,所以sum[n]-sum[i+1]-sum[n-i-1]可能是负数,要(+mod)%mod
【Accepted】
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <vector>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <deque>
#include <stack>
#include <string>
#include <bitset>
#include <ctime>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=3e5+;
const ll mod=1e9+;
int a[maxn];
int n;
ll sum[maxn];
ll two[maxn]; void Init()
{
two[]=;
for(int i=;i<=maxn;i++)
{
two[i]=(two[i-]*)%mod;
}
}
int main()
{
Init();
while(~scanf("%d",&n))
{
memset(sum,,sizeof(sum));
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
}
sort(a+,a+n+);
for(int i=;i<=n;i++)
{ sum[i]=(sum[i-]+(ll)a[i])%mod;
}
ll ans=;
for(int i=;i<=n-;i++)
{
ans=(ans+two[i]*(sum[n]-sum[n-i-]-sum[i+]+mod)%mod)%mod;
}
cout<<ans<<endl;
}
return ;
}
最新文章
- 抓包工具--Fiddler及charles的使用
- Guava并发:ListenableFuture与RateLimiter示例
- DFS(连通块) ZOJ 2743 Bubble Shooter
- 两分钟了解REACTIVEX
- spring mvc静态资源文件的引用
- HybridApp iOS ATS解决方案
- [转]Entity Framework技术导游系列开篇与热身
- .NET-提取字符串实践总结
- 在Linux最大打开文件数限制下 MySQL 对参数的调整
- iOS_SN_CoreDate(一)封装使用
- ASP.NET MVC3 系列教程 – 新的Layout布局系统
- 关于打开Eclipse时出现eclipse failed to create the java virtual machine与locking is not possible in the directory问题的解决
- Android - 分享内容 - 添加一个简单的分享操作
- ThinkPHP的使用
- linux驱动---字符设备的注册register_chrdev说起
- 组合模式 合成模式 COMPOSITE 结构型 设计模式(十一)
- /var/spool/clientmqueue目录~清理
- 【模板】多项式乘法(FFT)
- 使用cgroups来控制内存使用
- AVMoviePlayer 视频播放器