时间限制:
10000ms
单点时限:
1000ms
内存限制:
256MB
描述
给定N个整数A1, A2, ... AN,小Hi希望从中选出M个整数,使得任意两个选出的整数的差都是K的倍数。
请你计算有多少种不同的选法。由于选法可能非常多,你只需要输出对1000000009取模的结果。
输入
第一行包含三个整数N、M和K。
第二行包含N个整数A1, A2, ... AN。
对于30%的数据,2 ≤ M ≤ N ≤ 10
对于100%的数据,2 ≤ M ≤ N ≤ 100 1 ≤ K, Ai ≤ 100
输出
一个整数表示答案。
5 3 2 1 2 3 4 5样例输出
1
同余有些性质会用到:同余定理详解
对于同一个模数m,如果a和b同余,x和y同余,那么a+x和b+y也同余
如果两个数a和b之差能被m整除,那么我们就说a和b对模数m同余(即a和b除以m的余数相同)
满足自反性(一个数永远和自己同余)、
对称性(a和b同余,b和a也就同余)
传递性(a和b同余,b和c同余可以推出a和c同余)。
如果a≡b(mod m),x≡y(mod m),则a+x≡b+y(mod m)。
如果a≡b(mod m),x≡y(mod m),则ax≡by(mod m)。
如果ac≡bc(mod m),且c和m互质,则a≡b(mod m) (就是说同余式两边可以同时除以一个和模数互质的数)。
求排列组合是
d[i][j]=d[i-1][j-1]+d[i-1][j]//在i个数里取j个数的排列方式有几种
#include<bits/stdc++.h>
#define mod 1000000009
using namespace std;
typedef long long ll;
int d[110][110];
int t[110];
int main()
{
int n,m,k,a;
while(~scanf("%d%d%d",&n,&m,&k))
{
memset(d,0,sizeof(d));
d[0][0]=0;
for(int i=1;i<=n;i++)
{
d[i][0]=d[i][i]=1;
for(int j=1;j<i;j++)
{
d[i][j]=(d[i-1][j-1]+d[i-1][j])%mod;
}
}
for(int i=0;i<n;i++)
{
scanf("%d",&a);
t[a%k]++;
}
ll sum=0;
for(int i=0;i<k;i++)
{
if(t[i]>=m)
{
sum=(sum+d[t[i]][m])%mod;
}
}
sum%=mod;
printf("%lld\n",sum%mod);
}
}