经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » 编程经验 » 查看文章
一种递推组合数前缀和的Trick
来源:cnblogs  作者:自为风月马前卒  时间:2018/10/8 8:49:30  对本文有异议

记录一下一种推组合数前缀和的方法

Trick

\(\sum_{i = 0}^m C_n^i = S(n, m)\)

\(S\)是可以递推的

  • \(S(n, m + 1) = S(n, m) + C_{n}^{m + 1}\)

就是加上最末尾的一项

  • \(S(n + 1, m) = 2S(n, m) - C_n^m\)

\(S(n, m)\)可以看做是杨辉三角上的一行,而\(S(n+1, m)\)是他的下一行

考虑组合数的递推公式,除了\(C[n][m]\)这一项之外都会被计算两次、

另外如果有多组询问的话可以用莫队实现

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int N, M, Lim, C[1001][1001], S[1001][1001];
  4. int Make1() {
  5. for(int i = 0; i <= Lim; i++) {
  6. C[i][0] = C[i][i] = 1;
  7. for(int j = 1; j < i; j++)
  8. C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
  9. }
  10. return C[N][M];
  11. }
  12. void Make2() {
  13. /*for(int i = 0; i <= Lim; i++) {
  14. S[i][0] = 1;
  15. for(int j = 1; j <= i; j++)
  16. S[i][j] = S[i][j - 1] + C[i][j];
  17. }*/
  18. for(int i = 0, base = 1; i <= Lim; i++, base <<= 1) {
  19. S[i][i] = base;
  20. for(int j = i + 1; j <= Lim; j++)
  21. S[j][i] = 2 * S[j - 1][i] - C[j - 1][i];
  22. }
  23. }
  24. void print(int (*a)[1001]) {
  25. for(int i = 0; i <= Lim; i++, puts("")) {
  26. for(int j = 0; j <= i; j++)
  27. printf("%d ", S[i][j]);
  28. }
  29. }
  30. main() {
  31. Lim = 10;
  32. //cin >> N >> M;
  33. Make1();
  34. Make2();
  35. print(S);
  36. }
 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号