题目
组合数表示的是从n个物品中选出m个物品的方案数。举个例子,从(1,2,3) 三个物品中选择两个物品可以有 (1,2),(1,3),(2,3)这三种选择方法。根据组合数的定义,我们可以给出计算组合数的一般公式:
其中n!=1×2×⋯×n;特别地,定义0!=1。
小葱想知道如果给定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) 满足
输入输出样例
输入样例
1 2
3 3
输出样例
1
解析
这个题目首先使用的是组合数的递推公式进行计算,然后利用前缀优化计算。
#include<iostream>
using namespace std;
int n,t,k,m;
int c[2005][2005],s[2005][2005];
void prepare(){c[1][1]=c[1][0]=c[0][0]=1;for(int i=2;i<=2000;i++){c[i][0]=1;for(int j=1;j<=i;j++){c[i][j]=(c[i-1][j]+c[i-1][j-1])%k;//求出结果在这里取模 s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1];//利用前缀和 if(!c[i][j]){s[i][j]++;}}s[i][i+1]+=s[i][i];//继承前面计算过的 }
}
int main(){cin>>t>>k;prepare();while(t--){cin>>n>>m;if(m>n){m=n;}cout<<s[n][m]<<endl;}return 0;
}