Codeforces Round #697 (Div. 3) E. Advertising Agency

翻译:

玛莎在一家广告公司工作。为了推广新品牌,她想和一些博主签约。玛莎总共有𝑛个不同的博主。编号为𝑖的博主拥有𝑎𝑖名粉丝。

由于玛莎的预算有限,她只能与𝑘不同的博主签约。当然,玛莎希望她的广告被尽可能多的人看到。因此,她必须雇佣拥有最大粉丝总数的博主。

帮助她,找到选择𝑘博主的方法,这样他们的粉丝总数是最大的。如果第一种方式至少有一个博主,而第二种方式没有,那么两种方式就被认为是不同的。Masha认为所有的博主都有不同的粉丝(也就是说,没有一个粉丝会关注两个不同的博主)。

例如,如果𝑛=4,𝑘=3,𝑎=[1,3,1,2],那么Masha有两种方法来选择3个粉丝总数最大的博主:

与数字1、2和4的博主签订合同。在这种情况下,关注者数量将等于𝑎1+𝑎2+𝑎4=6。
与第2、3和4号博主签订合同。在这种情况下,关注者数量将等于𝑎2+𝑎3+𝑎4=6。
因为答案可以很大,所以对109+7取模输出。

输入
第一行包含一个整数𝑡(1≤𝑡≤1000)——测试用例的数量。然后是𝑡测试用例。

每个测试用例的第一行包含两个整数𝑛和𝑘(1≤𝑘≤𝑛≤1000)——博主的数量以及您可以与其中的多少人签订合同。

每个测试用例的第二行包含𝑛整数𝑎1,𝑎2,…𝑎𝑛(1≤𝑎𝑖≤𝑛)-每个博主的粉丝数。

可以保证所有测试用例中𝑛的总和不超过1000。

输出
对于每个测试用例,在单独的一行上输出一个整数——选择𝑘博主的方法的数量,这样他们的粉丝总数就可能是最大的。

例子
inputCopy
3.
4个3
1 3 1 2
4个2
1 1 1 1
2 1
1 2
outputCopy
2
6
1
请注意
测试用例在语句中进行了解释。

在第二个测试用例中,以下方法是有效的:

与数字1和2的博主签订合同。在这种情况下,关注者的数量将等于𝑎1+𝑎2=2;
与数字1和3的博主签订合同。在这种情况下,关注者的数量将等于𝑎1+𝑎3=2;
与1号和4号博主签订合同。在这种情况下,关注者的数量将等于𝑎1+𝑎4=2;
与2号和3号博主签订合同。在这种情况下,关注者的数量将等于𝑎2+𝑎3=2;
与2号和4号博主签订合同。在这种情况下,关注者的数量将等于𝑎2+𝑎4=2;
与3号和4号博主签订合同。在这种情况下,关注者数量将等于𝑎3+𝑎4=2。
在第三个测试用例中,以下方式是有效的:

和一个2号博主签了合同。在这种情况下,关注者的数量将等于𝑎2=2。

思路:这道题简单来说,就是求最大值的方案数,刚开始看了一眼还以为是dp,后来一想,就是一道组合数的板子。n个拿k个最大,我们只需要确定第k大的,一共有几个,和需要拿几个即可。就是典型的组合数。代码用了组合数预处理,前边博客写过,O(m)复杂度,可以说是最快的了。

代码:

/*Looking! The blitz loop this planet to search way
 
 Only my RAILGUN can shoot it 今すぐ
 
 身体中を  光の速さで
 
 駆け巡った確かな予感
 
 掴め! 望むものなら残さず
 
 輝ける自分らしさで
 
 信じてるよ  あの日の誓いを
 
 この瞳に光る涙それさえも  強さになるから
 
 */
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <stdio.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<tuple>
#include<numeric>
#include<stack>
using namespace::std;
typedef long long  ll;
int n,t;
inline __int128 read(){
    __int128 x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if(ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}
inline void print(__int128 x){
    if(x < 0){
        putchar('-');
        x = -x;
    }
    if(x > 9)
        print(x / 10);
    putchar(x % 10 + '0');
}

ll dp[1000005];
int a[1005],m;
const ll N=1e9+7;
ll inv(ll x, ll y) {
    ll re = 1;
    while (y) {
        if (y & 1) {
            re = re * x % N;
        }
        x = x * x % N;
        y /= 2;
    }
    return re % N;
}
ll rt[10005];
ll rte[10005];
ll zud(ll a,ll b){
    if (a==b) {
        return 1;
    }
    if (b>a) {
        return 0;
    }
    return rt[a]*rte[b]%N*rte[a-b]%N;
}
int fsl=1;
void wanyurukong(){
    cin>>n>>m;
//    printf("%d ",fsl);fsl++;
    for (int i =1; i<=n; i++) {
        cin>>a[i];
    }
    ll an=0;
    sort(a+1, a+1+n);
    an=a[n-m+1];
    int ff=1;
    int l=n-m;
    while (a[l]==an&&l>=1) {
        l--;
        ff++;
    }
//    printf("%d ",ff);
    l=n-m+2;
    int dd=1;
    while (a[l]==an&&l<=n) {
        dd++;
        l++;
        ff++;
    }
//    printf("%d %d\n",ff,dd);
    printf("%lld\n",zud(ff, dd));
//    for (int i =1; i<=an; i++) {
//        dp[i]=0;
//    }
//    for (int i  =1; i<=n; i++) {
//        for (int j=an; j>=a[i]; j--) {
//            dp[j]=(dp[j]+dp[j-a[i]])%N;
//        }
//        for (int k=0; k<=an; k++) {
//            printf("%lld ",dp[k]);
//        }printf("\n");
//    }
    
//    printf("%lld\n",dp[an]);
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(); cout.tie();
    cin>>t;
    dp[0]=1;
    rt[0]=rte[0]=1;
    for (int i =1; i<=10005; i++) {
        rt[i]=rt[i-1]*i%N;
        rte[i]=rte[i-1]*inv(i, N-2)%N;
    }
    while (t--) {
        wanyurukong();
    }
    //wanyurukong
    return 0;
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值