atcoder057D(组合数模板)

题目链接:http://abc057.contest.atcoder.jp/tasks/abc057_d

题意:给出n个数,可以选择x~y个数,使其平均值最大,求其最大平均数以及选择方案数。

思路:只考虑两种情况即可:

  1. 最大的数出现次数大于x, 那么最大平均数及为最大数,选择方案数为C(b[0], i)  x<=i<=min(y, b[0]); //其中b[0]为最大数出现的次数

  2. 最大数出现的次数小于x, 那么我们只需要考虑最末尾那个数即可;

代码:

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <stdio.h>
 4 #define ll long long
 5 #define MAXN 60
 6 using namespace std;
 7 
 8 ll a[MAXN], b[MAXN], c[MAXN][MAXN];
 9 
10 void gelou(void){//组合模板
11     c[1][0]=c[1][1]=1;
12     for(int i = 2; i<MAXN; i++){
13         c[i][0]=1;
14         for(int j = 1; j<MAXN; j++){
15             c[i][j]=(c[i-1][j]+c[i-1][j-1]);
16         }
17     }
18 }
19 
20 int main(void){
21     gelou();
22     ll n, x, y;
23     cin >> n >> x >> y;
24     for(int i=0; i<n; i++){
25         cin >> a[i];
26     }
27     sort(a, a+n);
28     ll pos=0, cc=a[n-1];
29     for(int i=n-1; i>=0; i--){//记录每个数出现的次数
30         if(a[i]==cc){
31             b[pos]++;
32         }else{
33             cc=a[i];
34             pos++;
35             b[pos]++;
36         }
37     }
38     pos++;
39     ll gg=0, num=0;
40     if(b[0]>=x){//最大的数出现的次数大于等于x
41         for(int i=x; i<=min(b[0], y); i++){
42             num+=c[b[0]][i];
43         }
44         printf("%.6lf
", (double)a[n-1]);
45         printf("%lld
", num);
46         return 0;
47     }
48     for(int i=0; i<pos; i++){
49         if(gg+b[i]>=x){
50             ll f=x-gg;
51             num=c[b[i]][f];//只考虑最后一个值的选择情况
52             break;
53         }else{
54             gg+=b[i];
55         }
56     }
57     double ave=0;
58     for(int i=n-1,j=0; j<x; j++,i--){
59         ave+=a[i];
60     }
61     ave/=x;
62     printf("%.6lf
", ave);
63     printf("%lld
", num);
64     return 0;
65 }
View Code
原文地址:https://www.cnblogs.com/geloutingyu/p/6628483.html