Description
Input
第一行有两个整数t, k,其中t代表该测试点总共有多少组测试数据,k的意义见【问题描述】。
接下来t行每行两个整数n, m,其中n, m的意义见【问题描述】。
Output
t行,每行一个整数代表所有的0<=i<=n,0<=j<=min(i,m)中有多少对(i, j)满足C(j,i)是k的倍数。
Sample Input
输入1:
1 2
3 3
输入2:
2 5
4 5
6 7
Sample Output
输出1:
1
输出2:
0
7
Hint
样例1提示:
在所有可能的情况中,只有C(1,2)是2的倍数。
输出范围:
题解:
这个题目可能是所有day2题目中最水的了吧,首先我们要知道一个公式c[i][j]=c[i-1][j]+c[i-1][j-1],然后给c[i][0]和c[1][1]赋初值1,就能很快求出每个c[i][j],但会爆long long,我们思考如果c[i][j]%k==0,那么必然c[i][j]=k*h+u(h,u为常数),所以能否整除k,关键是看u,如果u可以之后加上某个数整除k那么c[i][j]就可以整除k,所以我们一边取%k一边推并不影响结果,但之后还是会t掉,所以我们每行统计一下答案,最后逐行加起来就可以了。
代码:
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <cmath> #include <iostream> #define ll long long #define MAXN 3000 ll c[MAXN][MAXN]; ll ans[MAXN][MAXN]; int n,m,k,t; using namespace std; int main() { cin>>t>>k; c[1][1]=1;c[1][0]=1;c[0][0]=1; for(int i=2;i<=2010;i++){ for(int j=0;j<=2010;j++){ if(j==0) c[i][j]=1; else c[i][j]=c[i-1][j]+c[i-1][j-1],c[i][j]%=k; } } for(int i=1;i<=2010;i++){ for(int j=0;j<=2010;j++){ ans[i][j]=ans[i][j-1]; if(c[i][j]%k==0) ans[i][j]++; } } while(t--){ int anss=0; cin>>n>>m; for(int i=0;i<=n;i++) anss+=ans[i][min(i,m)]; printf("%d ",anss); } return 0; }