题目大意:给定$n,m,k$,对于所有的$0leq ileq n,0leq jleq min(i,m)$有多少对$(i,j)$满足$k|C_{i}^{j}$。
题解:预处理,在运用$C_{n}^{m}=C_{n-1}^{m-1}+C_{n-1}^{m}$求组合数的过程中顺便求一下$f(n,m)=|{i|iin [0,m]且k|C_{n}^{i}}|$。每次询问,运用循环求$sum_{i=0}^{n}f(i,min(i,m))$即可。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <ctime>
using namespace std;
#define ll long long
const int MAX_N = 2010, MAX_M = 2010;
int Prifix[MAX_N][MAX_M];
int K;
void SetPrifix(int n, int m)
{
static int C[MAX_N];
C[0] = 1;
Prifix[0][0] = 0;
for (int i = 1; i <= n; i++)
{
for (int j = min(i, m); j >= 0; j--)
{
if (i == j || j == 0)
C[j] = 1;
else
C[j] = (C[j - 1] + C[j]) % K;
}
Prifix[i][0] = (C[0] == 0);
for (int j = 1; j <= min(i, m); j++)
Prifix[i][j] = Prifix[i][j - 1] + (C[j] == 0);
}
}
int Find(int n, int m)
{
int ans = 0;
for (int i = 1; i <= n; i++)
ans += Prifix[i][min(i, m)];
return ans;
}
int main()
{
int caseCnt, n, m;
scanf("%d%d", &caseCnt, &K);
SetPrifix(2000, 2000);
while (caseCnt--)
{
scanf("%d%d", &n, &m);
printf("%d
", Find(n, m));
}
return 0;
}