小葱想知道如果给定 n,m 和 k,对于所有的 0≤i≤n,0≤j≤min(i,m) 有多少对 (i,j)(i,j) 满足 Ci取j 是 k 的倍数。
输入格式:
第一行有两个整数 t,kt,k,其中 tt 代表该测试点总共有多少组测试数据,k 的意义见问题描述。
接下来 tt 行每行两个整数 n,m,其中 n,m 的意义见问题描述。
输出格式:
共 t行,每行一个整数代表所有的0≤i≤n,0≤j≤min(i,m) 中有多少对 (i,j)(i,j) 满足Ci取j是 k 的倍数。
输入样例#1:
1 2
3 3
输出样例#1:
1
输入样例#2:
2 5
4 5
6 7
输出样例#2:
0
7
dp[n][m]即为所求答案的意思,则有公式:
dp[i][j]=dp[i-1][j]+f[i][j] f[i][j]=C(i,k)% k==0的个数,0<=k<=j
又有f[i][j]=f[i][j-1]+(C(i,j)%k ==0 ),
C[i][j]=(c[i-1][j-1]+c[i]-1[j])%k , 因为a=b+c, a%k=(b%k+c%k)%k
一题三个dp。。。。
#include<bits/stdc++.h>
using namespace std;
char buf[1<<17],*L=buf,*R=buf;
inline char gc() {
return L==R&&(R=(L=buf)+fread(buf,1,1<<17,stdin),L==R)?EOF:*L++;
}
template<typename T>
inline void read(T&x) {
int flag=x=0;
char ch=gc();
while (ch<'0'||ch>'9')
flag|=ch=='-',ch=gc();
while (ch>='0'&&ch<='9')
x=(x<<3)+(x<<1)+ch-48,ch=gc();
if(flag)
x=-x;
}
const int MAXN=2e3+3;
int dp[MAXN][MAXN],f[MAXN][MAXN],c[MAXN][MAXN];
int t,k;
int main() {
freopen("in.txt","r",stdin);
read(t),read(k);
c[0][0]=1%k;
for(int i=1; i<MAXN; ++i) {
c[i][0]=1%k;
for(int j=1; j<=i; ++j) {
c[i][j]=(c[i-1][j-1]+c[i-1][j])%k;
}
}
f[0][0]=(c[0][0]==0);
for(int i=1; i<MAXN; ++i) {
f[i][0]=(c[i][0]==0);
for(int j=1; j<MAXN; ++j) {
if(j>i)
f[i][j]=f[i][j-1];
else
f[i][j]=f[i][j-1]+(c[i][j]==0);
}
}
dp[0][0]=f[0][0];
for(int i=1; i<MAXN; ++i) {
for(int j=0; j<MAXN; ++j) {
dp[i][j]=dp[i-1][j]+f[i][j];
}
}
int x,y;
while(t--) {
read(x),read(y);
printf("%d\n",dp[x][y]);
}
return 0;
}