给定N个整数A1, A2, ... AN,小Hi希望从中选出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一个整数表示答案。
5 3 2 1 2 3 4 5Sample Output
1
简单题!就是逆元有点不会!所以不用逆元换了一种方法。
任意两个数的差是k的倍数,那么两个数取余k后相等,比如3 5的差是2的倍数,两个取余2都是1。
然后就是在所有任意两数差都是k倍数的组中取m个,比如10中取3就是10!/(10-3)!*3!
10*9*8*7*6*5*4*3*2*1/7*6*5*4*3*2*1*3*2*1=10*9*8/3*2.在取余中不能有除法和减法。
10*9*8/3*2=5*3*2,这里把除法消去变成了5*3*2,原理是不是很简单,代码实现也就是用数组把
10,9,8装起来,然后用3,2和他们消一下。
代码如下;
#include<stdio.h>
#include<algorithm>
#define mod 1000000009
using namespace std;
int a[110];
int b[110];
int c[110];
long long jzqj(int s,int x)
{
long long ans=1;
int p,gys;
for(int i=x+1;i<=s;i++)
{
c[i]=i;//数组把它们装起来
}
for(int i=1;i<=s-x;i++)
{
int p=i;
while(p>1)
{
for(int j=x+1;j<=s;j++)
{
gys=__gcd(c[j],p);
if(c[j]>=gys&&p>=gys)//判断他们能不能除
{
c[j]/=gys;
p/=gys;
}
if(p==1)
break;
}
}
}
for(int i=x+1;i<=s;i++)
{
ans*=c[i];
ans%=mod;
}
return ans;
}
int main()
{
int n,m,k,o,pan;
long long ans;
while(~scanf("%d%d%d",&n,&m,&k))
{
o=0;ans=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
a[i]%=k;
}
for(int i=1;i<=n;i++)
{
pan=1;
if(a[i]>=0)
{
for(int j=i+1;j<=n;j++)
{
if(a[j]==a[i])
{
a[j]=-1;
pan++;
}
}
b[o++]=pan;//把任意两数相减等于k的倍数的组存入b中。
}
}
for(int i=0;i<o;i++)
{
if(b[i]>=m)
{
ans+=jzqj(b[i],m);
ans%=mod;
}
}
printf("%lld\n",ans);
}
}