组合数 Cmn 表示的是从 n 个物品中选出 m 个物品的方案数。
举个例子,从 (1, 2, 3) 三个物品中选择两个物品可以有 (1, 2), (1, 3), (2, 3) 这三种选择方法。
根据组合数的定义,我们可以给出计算组合数 Cmn 的一般公式:
其中 n! = 1 × 2 × · · · × n 。
小葱想知道如果给定 n, m 和 k ,对于所有的 0 ≤ i ≤ n, 0 ≤ j ≤ min(i, m) 有多少对 (i, j) 满足 Cji 是 k 的倍数。
输入格式
第一行有两个整数 t, k ,其中 t 代表该测试点总共有多少组测试数据,k 的意义见问题描述。
接下来 t 行每行两个整数 n, m ,其中 n, m 的意义见问题描述。
输出格式
共 t 行,每行一个整数代表所有的 0 ≤ i ≤ n, 0 ≤ j ≤ min(i, m) 有多少对 (i, j) 满足 Cji 是 k 的倍数。
数据范围
n,m≤2000,2≤k≤21,t≤10^4
输入样例:
1 2
3 3
输出样例:
1
代码如下:
#include <iostream>
using namespace std;
const int N = 2010;
int c[N][N],s[N][N];int main()
{int cnt = 0,k = 0;cin>>cnt>>k;for (int i = 0;i<N;i++)for (int j = 0;j<=i;j++){if (!j) c[i][j] = 1%k;else c[i][j] = (c[i-1][j]+c[i-1][j-1])%k;if (!c[i][j]) s[i][j] = 1;}for (int i = 0;i<N;i++)for (int j = 0;j<N;j++){if(i) s[i][j] +=s[i-1][j];if (j) s[i][j] +=s[i][j-1];if (i&&j) s[i][j] -=s[i-1][j-1];}while(cnt--){int n,m;cin>>n>>m;cout<<s[n][m]<<endl;}return 0;
}