Gorun
2019-11-08 20:43:23
首先看到这道题,可以使用暴力,具体思路如下。
组合数里面有阶乘,求一个数的阶乘可以使用如下递推公式:
再结合组合数公式:
可以枚举所有的
但是这样写有两个问题:
时间复杂度过高:计算单次
精度问题,
所以我们可以先把前面的
“这不就是杨辉三角吗?”
当然大神们可以省略以上的分析步骤直接得出杨辉三角的结论。
有了杨辉三角,我们就把原本的阶乘乘除解决了,可以使用递推法,精度问题也不需要担心,毕竟
其实就是利用了前缀和的思想,不过需要注意的是当
附源代码:
#include <cstdio>
#include <iostream>
using namespace std;
typedef long long ll;
const int MAXN=2010;
const int MAXT=1010;
int t;
struct Task{
ll a,b;
}task[MAXT];
ll n,m,k,c[MAXN][MAXN],ans[MAXN][MAXN];
inline void solve()
{
c[0][0]=1;
for (ll i=1;i<=2000;i++)
{
c[i][0]=1;
for (ll j=1;j<=i;j++)
{
c[i][j]=(c[i-1][j]+c[i-1][j-1])%k;
ans[i][j]=ans[i-1][j]+ans[i][j-1]-ans[i-1][j-1]+(c[i][j]?0:1);
}
ans[i][i+1]=ans[i][i];
}
}
int main()
{
scanf("%d%lld",&t,&k);
solve();
while (t--)
{
int a,b;
scanf("%d%d",&a,&b);
printf("%lld\n",ans[a][min(a,b)]);
}
}