cf840A Leha and function

哇这个意义不明的公告……欺负英语水平差的人不会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,jMi>=Nj 。现在,请你重新排列M数组变为M’,使得 F(Mi,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元组有 Ck1n1 ,除此外包含2的k元组有 Ck1n2 个,以此类推,包含n-k+1的k元组应当有 Ck1nk+1=1 个。
所以要求的数学期望就是
ki=1iCk1niCkn
这东西我是不会化简,有位神犇化简出来结果是这样的: (n+1)(nk)(k+1)(k+2)
显然我们让n尽可能大,让k尽可能小就行了。

但是很显然,这东西不太好化简,所以我们不妨来猜想一下。
在一串数中,期望越大就是想让最大比较大的项比较多。怎么做呢?显然n比较大且k比较小的时候,就能保证更大的最大项。至于这个猜想对不对呢?看看样例,好像是对的,别犹豫,写吧。

当然,我觉得最简单的方法还是:看看样例,凭着敏感和猜测,发现要让k最小的一项对应n最大的一项,嗯。


实现的话开个结构体存一下值和次序然后带快排即可。

#include <bits/stdc++.h>
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.value<y.value;
}
int 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<<b[i]<<" ";
    return 0;

} 

pupil的日子何时才是一个尽头啊……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值