【NOIP2016】组合数问题
本题在洛谷上的链接:https://www.luogu.org/problemnew/show/P2822
就在十一假期某学堂里有幸听出题人zhx大神讲课。。。
都说是水题,但还是需要技巧滴。首先得知道组合数的那个在杨辉三角里体现得淋漓尽致的性质:c[n][m]=c[n-1][m-1]+c[n-1][m]。
考虑到多组数据,但k是一定的,可以再开个数组来存到(i,j)时在第i行前j个的答案数,然后对应查询累加即可。
本以为这样就能过的,可是只有55分?输出中间结果一看,溢出了。。。
优化一下,判断是否能被k整除时,直接c[i][j]%=k就好,若是0则令答案数加1。
1 #include <cstdio> 2 #include <algorithm> 3 4 using namespace std; 5 6 const int mmax = 2005, maxt = 1e4 + 5; 7 8 int in[maxt], im[maxt], tri[mmax][mmax], ans[mmax][mmax]; 9 10 int main() { 11 int t, k, maxn = 0; 12 scanf("%d%d", &t, &k); 13 for (int i = 1; i <= t; ++i) { 14 scanf("%d%d", &in[i], &im[i]); 15 maxn = max(maxn, in[i]); 16 } 17 for (int i = 0; i <= maxn; ++i) 18 for (int j = 0; j <= i; ++j) { 19 if (!j || j == i) { 20 tri[i][j] = 1; 21 if (j == i) ans[i][j] = ans[i][j - 1]; 22 } 23 else { 24 tri[i][j] = (tri[i - 1][j - 1] + tri[i - 1][j]) % k; 25 if (!tri[i][j]) ans[i][j] = ans[i][j - 1] + 1; 26 else ans[i][j] = ans[i][j - 1]; 27 } 28 } 29 for (int i = 1; i <= t; ++i) { 30 int out = 0; 31 for (int j = 0; j <= in[i]; ++j) 32 if (j <= im[i]) out += ans[j][j]; 33 else out += ans[j][im[i]]; 34 printf("%d\n", out); 35 } 36 return 0; 37 }