lql-nyist

这次到渣渣问桶桶了。。。

准备给你n个数a1, a2, ... an,桶桶你能从中找出m个特别的整数吗,我想让任意两个之差都是k的倍数。

请你计算有多少种不同的选法。由于选法可能非常多,你只需要输出对1000000009取模的结果。

Input 第一行包含三个整数n、m和k。

第二行包含n个整数a1, a2, ... an。

对于30%的数据,2 ≤ m ≤ n ≤ 10

对于100%的数据,2 ≤ m ≤ n ≤ 100 1 ≤ k, ai ≤ 100

Output 一个整数表示答案。

Sample Input
5 3 2  
1 2 3 4 5
Sample Output
1

思路

  • [ ] 题意:给我们n个数,让我们找出 由m个数组成的方案数(组成的这m个数的中的任意两个之间相差都要是k)
  • [ ] 分析:让这个n个数 都取余k,那么余数相同的 数之间必定相差都是k,所以我们可以同 桶排 中的桶 去统计 在这个n个数中余数为1到k-1的数的个数,之后对于 对于每个余数我们考虑:看它的个数是否大于等于m,如果大于的话我们就用数学中的 排列组合知识 去求方案数。
  • 特别注意在 排列方案数\(C_x^y\)的时候,时候我们不能 乘完再除,这样有可能超 long long,所以要边乘边除 主要代码如下
ll ans = 1
for(int i = 1; i <= y; i ++)
	ans = ans*(x + 1 - i) / i ;

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;


#define ll long long 
const ll mod = 1000000009;

ll work(ll n, ll m)
{
    ll res = 1;
    /* for(int i = n; i >= n - m + 1; i --) */
    /*     res *= i; */
    /* for(int i = 1; i <= m; i ++) */
    /*     res /= i; */
    for(int i = 1; i <= m; i ++)
        res = res*(n + 1 - i)/i;
    return res;
}

int main()
{
    /* freopen("A.txt","r",stdin); */
    ll n, m, k;
    scanf("%lld %lld %lld", &n, &m, &k);
    int x;
    int bar[105] = {0};
    for(int i = 1; i <= n; i ++)
    {
        scanf("%d", &x);
        bar[x % k] ++;
    }
    ll ans = 0;
    for(int i = 0; i < k; i ++)
    {
        if(bar[i] >= m)
            ans += work(bar[i], m), ans %= mod;
    }
    printf("%lld\n", ans);

    return 0;
}

分类:

技术点:

相关文章: