哇这个意义不明的公告……欺负英语水平差的人不会any是吧……
题意:
有一个函数F(a,b),其定义如下:
集合A为{1,2,3,…,n},集合B为A中所有元素个数为b的子集。F(a,b)表示的是B中所有集合的最小值的期望。
例如,F(4,2)表示,A={1,2,3,4},B={{1,2},{1,3},{1,4},{2,3},{2,4},{3,4}},因此,B中的最小值的期望就是1* 12 +2* 13 +3* 16 =1.66667
但是Leha是个无聊的人,他不满足于求这个值。现在有两个数组M,N,满足 ∀i,j,Mi>=Nj恒成立 。现在,请你重新排列M数组变为M’,使得 ∑F(M′i,Ni) 取得最大值。
样例:(先埋个伏笔)
input:
5
7 3 5 3 4
2 1 3 2 3
output:
4 7 3 5 3
input:
7
4 6 5 8 8 2 6
2 1 2 2 1 1 2
output:
2 6 4 5 8 8 6
虽然说什么最小值的最大值要带二分,不过这道题和二分大概毫无干系。
不过如果二分不了的话,又不像是数论,我们不妨先来看看能不能贪一把。
对函数F分析。如F(4,2),在对{1,2,3,4}操作时,包含1的二元组有 C13=3 个,除此外包含2的二元组有 C12=2 个,除此外包含3的二元组有 C11=1 个。
不妨做些拓展,对F(n,k),包含1的k元组有 Ck−1n−1 ,除此外包含2的k元组有 Ck−1n−2 个,以此类推,包含n-k+1的k元组应当有 Ck−1n−k+1=1 个。
所以要求的数学期望就是
∑ki=1i⋅Ck−1n−iCkn
这东西我是不会化简,有位神犇化简出来结果是这样的: (n+1)(n−k)(k+1)(k+2)
显然我们让n尽可能大,让k尽可能小就行了。
但是很显然,这东西不太好化简,所以我们不妨来猜想一下。
在一串数中,期望越大就是想让最大比较大的项比较多。怎么做呢?显然n比较大且k比较小的时候,就能保证更大的最大项。至于这个猜想对不对呢?看看样例,好像是对的,别犹豫,写吧。
当然,我觉得最简单的方法还是:看看样例,凭着敏感和猜测,发现要让k最小的一项对应n最大的一项,嗯。
实现的话开个结构体存一下值和次序然后带快排即可。
#include
using namespace std;
#define MAXN 200010
struct node{
int id;
int value;
}v[MAXN];
int a[MAXN],b[MAXN];
bool cmp1(int x,int y){
return x>y;
}
bool cmp2(node x,node y){
return x.valueint main(){
int k;
cin>>k;
for(int i=1;i<=k;++i)
cin>>a[i];
sort(a+1,a+k+1,cmp1);
for(int i=1;i<=k;++i){
v[i].id=i;
cin>>v[i].value;
}
sort(v+1,v+k+1,cmp2);
for(int i=1;i<=k;++i){
b[v[i].id]=a[i];
}
for(int i=1;i<=k;++i)
cout<" ";
return 0;
}
pupil的日子何时才是一个尽头啊……