You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

42 lines
1.5 KiB

2 years ago
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2010; //n的数值上限
int t; //t次查询
int n; //n个数字中
int m; //找m个数字组合
int K; //给定k求k的倍数
int C[N][N]; //组合数数组
int s[N][N]; //二维前缀和
int main() {
//默认初始值-1,之所以初始为-1是怕默认的0无法描述是模完变成的0还是天生默认就是0-1就有这个好处。
memset(C, -1, sizeof C);
cin >> t >> k;
//预处理杨辉三角形
for (int i = 0; i < N; i++) {
//base case
C[i][0] = C[i][i] = 1; //组合数C(n,0)=1 组合数C(n,n)=c(n,0)=1
//递推生成其它组合数
//因为是求组合数C(A,B)那么A一定要大于等于B否则就不对了。
//所以j的循环范围最大就只能是i
for (int j = 1; j < i; j++)//因为一头一尾j-->0和i都被手动设置了1所以循环的范围就是中间剩下的了。
C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % k;//因为C数组中已有的数据都是被%k后存入的
// 所以这里做加法前不用再%,再%也是那么回事,反而速度更慢了。
}
//标准的二维前缀和
for (int i = 1; i < N; i++)
for (int j = 1; j < N; j++)
s[i][j] = (C[i][j] == 0 ? 1 : 0) + s[i][j - 1] + s[i - 1][j] - s[i - 1][j - 1];
//处理t次询问
while (t--) {
cin >> n >> m;
cout << s[n][m] << endl;
}
}