问题 H: 组合数问题I
时间限制: 1 Sec 内存限制: 512 MB提交: 181 解决: 49
[ 提交][ 状态][ 讨论版][命题人: admin]
题目描述
组合数
表示的是从n个物品中选出m个物品的方案数。举个例子,从(1,2,3)三个物品中选择两个物品可以有(1, 2), (1, 3), (2, 3)这三种选择方法。根据组合数的定义,我们可以给出计算组合数
的一般公式:
其中n! = 1×2×...×n。
小葱想知道如果给定n, m和k,对于所有的0≤i≤n,0≤ j≤min(i,m)有多少对(i, j)满足
是k的倍数。



小葱想知道如果给定n, m和k,对于所有的0≤i≤n,0≤ j≤min(i,m)有多少对(i, j)满足

输入
第一行有两个整数t, k,其中t代表该测试点总共有多少组测试数据,k的意义见【问题描述】。接下来t行每行两个整数n, m,其中n, m的意义见【问题描述】。
输出
t行,每行一个整数代表所有的。0≤i≤n,0≤ j≤min(i,m)有多少对(i, j)满足
是k的倍数。

样例输入
1 2
3 3
样例输出
1
提示
在所有可能的情况中,只有以 是2的倍数。
#include<bits/stdc++.h>
using namespace std;
int a[2005][2005];
int s[2005][2005];
void Print(int k)
{
a[0][0]=1;
for(int i=1;i<=2000;i++)
{
for(int j=0;j<=i;j++)
{
if(j==0||j==i)a[i][j]=1;
else a[i][j]=(a[i-1][j-1]+a[i-1][j])%k;
}
}
int j=0;
for(int i=1;i<=2000;i++)
{
for( j=1;j<=i;j++)
{
s[i][j]=s[i][j-1]+s[i-1][j]-s[i-1][j-1];//矩阵前缀和
if(a[i][j]==0&&j<=i)s[i][j]++;
}
s[i][j]=s[i][j-1];//可以直接开2000*2000的循环//这里把随后一个值向后推以为方便下一行计算
}
}
int main()
{
int t,k;
ios::sync_with_stdio(0);
cin>>t>>k;
Print(k);
while(t--)
{
int n,m;
cin>>n>>m;
if(m>n)m=n;
cout<<s[n][m]<<endl;
}
}

分别对应 s (i-1, j-1) s(i-1,j) s(i,j-1) s(i,j)