题目描述
组合数表示的是从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的倍数。
输入
第一行有两个整数t,k,其中t表示该测试点总共有多少组测试数据,k的意义见「题目描述」。
接下来t行每行两个整数n,m,其中n,m的意义见「题目描述」。
输出
输出共t行,每行一个整数代表对于所有的 0 ≤ i ≤ n, 0 ≤ j ≤ min(i,m) 有多少对 (i, j) 满足
是k的倍数。
#include <iostream>
long long nums[2010][2010], ans[2010][2010];
int t, n, m, k;
void fun()
{nums[1][1] = 1;for (int i = 0; i <= 2006; i++){nums[i][0] = 1;for (int j = 1; j <= i; j++){nums[i][j] = (nums[i - 1][j] % k + nums[i - 1][j - 1] % k) % k;ans[i][j] = ans[i - 1][j] + ans[i][j - 1] - ans[i - 1][j - 1];if (nums[i][j] == 0) ans[i][j]++;}ans[i][i + 1] = ans[i][i];}
}
int main()
{scanf("%d%d", &t,&k);fun();while (t--){scanf("%d%d", &n, &m);printf("%lld\n", ans[n][std::min(m, n)]);}return 0;
}