Gym 100952D Time to go back 组合学、杨辉三角预处理组合数

D - D

Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:%I64d
& %I64u

Submit Status Practice Gym
100952D

Description

standard input/output

Statements

You have been out of Syria for a long time, and you recently decided to come back. You remember that you have M friends there and since you are a generous man/woman you want to buy a gift for each of them, so you went to a gift store that have N gifts, each
of them has a price.

You have a lot of money so you don‘t have a problem with the sum of gifts‘ prices that you‘ll buy, but you have K close friends among

your M friends you want their gifts to be expensive so the price of each of them is at least D.

Now you are wondering, in how many different ways can you choose the gifts?

Input

The input will start with a single integer T, the number of test cases. Each test case consists of two lines.

the first line will have four integers N, M, K, D (0 ?≤? N, M ?≤? 200, 0 ?≤? K ?≤? 50,
0 ?≤? D ?≤? 500).

The second line will have N positive integer number, the price of each gift.

The gift price is ?≤? 500.

Output

Print one line for each test case, the number of different ways to choose the gifts (there will be always one way at least to choose the gifts).

As the number of ways can be too large, print it modulo 1000000007.

Sample Input

Input

2
5 3 2 100
150 30 100 70 10
10 5 3 50
100 50 150 10 25 40 55 300 5 10

Output

3
126

Source

UESTC 2016 Summer Training #21

Gym 100952D

My Solution

组合学

有 n 个礼物, m个朋友, 其中k 个很要好的朋友, 要买 price 大于 d 的礼物

领 price >= d 的礼物个数为 cnt

则如果用 C[cnt][k] * C[n - k][m - k] 则显然不对, 因为这里面前面选的 price >= d的, 后面给普通好朋友选礼物的时候也会选到, 这样总的买的礼物数来说有大量重复了

所以 应该是分步 分类(price >= d 的与 < d 的分开算, 这样就不会相同的礼物选2次了)

首先 C[cnt][k]        *    C[n - cnt][m - k];

然后 C[cnt][k + 1]  *   C[n - cnt][ m - k - 1]

接着 C[cnt][k + 2]  *   C[n - cnt][ m - k - 2]

 ......

直到 k + 1 == cnt 或者 m - k - 1 < 0    //其中 如果k + 1 == cnt  则cnt 选完了,而 m - k - 1 < 0 则是 则是全都选了price >= d的了

复杂度 O(T * n)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 2*1e2 + 8;
const LL Hash = 1000000007;

inline LL mod(LL a)
{
    return a - (a/Hash)*Hash;
}

LL C[maxn][maxn], val[maxn];
inline void getC()
{
    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] = mod(C[i-1][j-1] + C[i-1][j]);
        }
    }
}

inline bool cmp(LL a, LL b)
{
    return a > b;
}

int main()
{

    #ifdef LOCAL
    freopen("a.txt", "r", stdin);
    //freopen("b.txt", "w", stdout);
    #endif // LOCAL
    getC();
    int T, n, m, k, d, cnt;
    LL ans;
    scanf("%d", &T);
    while(T--){
        cnt = 0; ans = 0;
        scanf("%d%d%d%d", &n, &m, &k, &d);
        for(int i = 0; i < n; i++){
            scanf("%I64d", &val[i]);
        }
        sort(val, val + n, cmp);
        for(int i = 0; i < n; i++){
            if(val[i] < d) break;
            else cnt++;
        }
        //cout<<cnt<<endl;
        //cout<<C[n - k][m - k]<<endl;
        for(int i = k; i <= cnt; i++){
            if(n - cnt == 0) break;
            if(m - i < 0) break;
            ans = mod(ans +  mod(C[cnt][i] * C[n - cnt][m - i]));

        }
        if(n - cnt == 0) ans = C[cnt][m];
        //ans = mod(C[cnt][k] * C[n - k][m - k]);
        if(cnt < k || n < m) printf("0\n");
        else printf("%I64d\n", ans);
    }
    return 0;
}

Thank you!

------from ProLights

时间: 2024-10-13 17:02:35

Gym 100952D Time to go back 组合学、杨辉三角预处理组合数的相关文章

LeetCode (13) Pascal&#39;s Triangle (杨辉三角 )

题目描述 Given numRows, generate the first numRows of Pascal's triangle. For example, given numRows = 5, Return 从第三行开始,每行除了最左边和最右边两个数为1,其他数字都是上一行中相邻两个数字之和.根据上述规则可以写出下面的代码: class Solution { public: vector<vector<int> > generateRow1() { vector<in

杨辉三角

1 package com.llh.demo; 2 3 /** 4 * 杨辉三角 5 * 6 * @author llh 7 * 8 */ 9 public class Test { 10 /* 11 * 杨辉三角 12 */ 13 public static void main(String[] args) { 14 int[] a = new int[11]; 15 int num = 1; 16 // 17 for (int i = 1; i <= 10; i++) { 18 for (i

杨辉三角实例菱形实例

杨辉三角实例 public class Hui { public static void main (String [] args){ int [][] a =new int [10][10]; for(int i=0;i<a.length;i++){ for(int j=0;j<=i;j++){ if(j==0||i==j){ System.out.print(" "+(a[i][j]=1)); }else {a[i][j]=a[i-1][j-1]+a[i-1][j];

js算法集合(二) javascript实现斐波那契数列 (兔子数列) Javascript实现杨辉三角

js算法集合(二)  斐波那契数列.杨辉三角 ★ 上一次我跟大家分享一下做水仙花数的算法的思路,并对其扩展到自幂数的算法,这次,我们来对斐波那契数列和杨辉三角进行研究,来加深对Javascript的理解. 一.Javascript实现斐波那契数列 ①要用Javascript实现斐波那契数列,我们首先要了解什么是斐波那契数列:斐波那契数列(Fibonacci sequence),又称黄金分割数列.因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为

使用Java打印杨辉三角

package 杨辉三角; import java.util.Scanner; public class 三角 { private static Scanner scn; public static void main(String[] args) { scn = new Scanner(System.in); System.out.println("请输入数据"); int n = scn.nextInt(); //定义一个二维数组 int [][] array = new int

Java的二维数组的应用及杨辉三角的编写

(1) 编写一个程序,生成一个10*10的二维随机整数数组,并将该数组的每行最大值保存于一个一维数组中,将每列平均值保存于另外一个一维数组中并分别输出. (2) 编程输出杨辉三角的前10行. 找出一个,即该位置上的元素在该行上最大,在该列上最小(注:一个二维数组也可能没有这样的鞍点). /** * * @author liuhui *@version Java上机实验三 *@time 2016.10.30 */ public class javatest2 { public static int

实现杨辉三角的10种解法--体验Python之美

本文收集了使用python实现杨辉三角的多种解法,主要为网上收集,也有一些是自己写的.从中可以体会python编写一个算法的不同思想和Python语法的特点. 杨辉三角是什么?还是度娘吧,看起来像是这样的:                          1                          1   1                           1   2   1                         1   3   3   1               

如何用C++打印杨辉三角

下面是杨辉三角的一部分,我们观察观察它有什么规律: 1 1      1 1     2     1 1     3     3     1 1     4     6     4     1 1     5    10    10    5    1 1     6    15    20   15    6    1 1     7     21    35   35   21   7    1 ................ 通过观察不难发现,三角的两边都是1,而且除边界外的每个数的值都

Pascal&#39;s Triangle II 杨辉三角

1 class Solution { 2 public: 3 vector<int> getRow(int rowIndex) { 4 vector<vector<int>> tri; 5 if(rowIndex==0) 6 { 7 vector<int> c; 8 c.push_back(1); 9 return c; 10 } 11 vector<int> b; 12 b.push_back(0); 13 b.push_back(1); 14