牛客OI赛制测试赛1 F子序列(组合数学+容斥)

Posted ITAK

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了牛客OI赛制测试赛1 F子序列(组合数学+容斥)相关的知识,希望对你有一定的参考价值。

题目描述

给出一个长度为n的序列,你需要计算出所有长度为k的子序列中,除最大最小数之外所有数的乘积相乘的结果

输入描述:

第一行一个整数T,表示数据组数。
对于每组数据,第一行两个整数N,k,含义如题所示

接下来一行N个整数,表示给出的序列

保证序列内的数互不相同

输出描述:

对于每组数据,输出一个整数表示答案,对取模
每组数据之间以换行分割
示例1

输入

3
4 3 
5 3 1 4
5 4
3 7 5 2 1
10 3 
100 1020 2050 102 12 235 4 57 32135 54354 

输出

144
81000
521918013

说明

      
       第一组数据解释
      
      
       所有长度为3的子序列为
       
      
      
       最终答案为
       
      



备注:

对于的数据:
对于的数据:
对于的数据:
保证序列中的元素互不相同且


解题思路:

     对于每个数字在长度为 k k 的子序列中出现的次数为 Cn1k1 次,这个地方解释一下,对于 ai a i 这个数来说,如果它出现在子序列中,那么总数还有 n1 n − 1 个 数字,序列的长度还有 k1 k − 1 个,所以结果为 Ck1n1 C n − 1 k − 1
    如果 ai a i 这个数字需要计入结果中,那么 ai a i 一定不是最大值或者最小值,所以我们从反面考虑:
     1) 假设 ai a i 是最大值的情况,那么我们首先将这个数组进行排序(下标从 0 0 开始),那么如果 ai 是最大值的话,那么一定有下标 i i 作为下标结束的末尾,我们只需要从前 i 个数中选取 k1 k − 1 个数即可,方法数为 Ck1i C i k − 1
     2) 同理, ai a i 是最小值的情况的方法数为 Ck1ni1 C n − i − 1 k − 1
综上,令 pi=Ck1n1Ck1iCk1ni1 p i = C n − 1 k − 1 − C i k − 1 − C n − i − 1 k − 1 对于 ai a i 这个数来说,它对答案的贡献为 apii a i p i
最终的答案为 : ans=n1i=0apii a n s = ∏ i = 0 n − 1 a i p i
最后,只需要预处理组合数取模即可。

代码如下

#include <iostream>
#include <algorithm>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
typedef long long LL;
const LL MOD = 1e9+7;
const int MAXN = 1e3+5;
int a[MAXN];
LL Pow(LL a, LL b)

    LL ans = 1;
    while(b)
    
        if(b&1) ans=ans*a%MOD;
        b>>=1;
        a=a*a%MOD;
    
    return ans;


LL c[MAXN][MAXN];
void Init()

    memset(c, 0, sizeof c);
    for(int i=0; i<MAXN; i++)
    
        c[i][0] = 1;
        for(int j=1; j<=i; j++)
        
            c[i][j] = (c[i-1][j] + c[i-1][j-1]) % (MOD-1);
        
    


int main()

    Init();
    int T; cin>>T;
    while(T--)
    
        int n, k; cin>>n>>k;
        for(int i=0; i<n; i++) cin>>a[i];
        sort(a, a+n);
        LL tmp = c[n-1][k-1];
        LL ans = 1;
        for(int i=0; i<n; i++)
        
            LL b = tmp-c[i][k-1]-c[n-i-1][k-1];
            b = (b%(MOD-1)+(MOD-1))%(MOD-1);
            ans = ans*Pow(a[i], b)%MOD;
        
        cout<<ans<<endl;
    
    return 0;

以上是关于牛客OI赛制测试赛1 F子序列(组合数学+容斥)的主要内容,如果未能解决你的问题,请参考以下文章

2021牛客暑期多校训练营5 D.Double Strings(容斥dp)

牛客数字染色莫比乌斯容斥

oi赛制啥意思

AtCoder Beginner Contest 214 F - Substrings(容斥dp)

OI内的排列与组合(简单版)

[bzoj 3622]已经没有什么好害怕的了