翻译:
玛莎在一家广告公司工作。为了推广新品牌,她想和一些博主签约。玛莎总共有𝑛个不同的博主。编号为𝑖的博主拥有𝑎𝑖名粉丝。
由于玛莎的预算有限,她只能与𝑘不同的博主签约。当然,玛莎希望她的广告被尽可能多的人看到。因此,她必须雇佣拥有最大粉丝总数的博主。
帮助她,找到选择𝑘博主的方法,这样他们的粉丝总数是最大的。如果第一种方式至少有一个博主,而第二种方式没有,那么两种方式就被认为是不同的。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;
}