经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C » 查看文章
SPOJTLE - Time Limit Exceeded(高位前缀和)
来源:cnblogs  作者:自为风月马前卒  时间:2018/11/6 10:17:48  对本文有异议

题意

题目链接

题目的意思是给一个数组C,长度为n,每个数字的范围是2^m,然后要求构造一个数组a,满足

1、a[i] % C[i] !=0 ;

2、a[i] < 2^m ;

3、a[i] & a[i+1] = 0;

Sol

直接dp的话就是先枚举补集的子集,这样的复杂度是\(3^n\)

然后补集的子集可以用高位前缀和优化一下

时间复杂度:\(O(2^n * n)\)

  1. #include<cstdio>
  2. #include<cstring>
  3. using namespace std;
  4. const int MAXN = 1e5 + 10, mod = 1000000000;
  5. inline int read() {
  6. char c = getchar(); int x = 0, f = 1;
  7. while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
  8. while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
  9. return x * f;
  10. }
  11. int N, M, a[MAXN], c[MAXN], f[51][65537], sum[51][65537];
  12. int add(int &x, int y) {
  13. x = (x + y >= mod ? x + y - mod : x + y);
  14. }
  15. int solve() {
  16. N = read(); M = read(); int Lim = (1 << M) - 1;
  17. memset(f, 0, sizeof(f));
  18. memset(sum, 0, sizeof(sum));
  19. f[0][0] = 1;
  20. for(int i = 0; i <= Lim; i++) sum[0][i] = 1;
  21. for(int i = 1; i <= N; i++) {
  22. c[i] = read();
  23. for(int sta = 1; sta <= Lim; sta ++) {
  24. if(!(sta % c[i])) continue;
  25. int s = (~sta) & Lim;
  26. sum[i][sta] = f[i][sta] = sum[i - 1][s];
  27. }
  28. for(int j = 0; j < M; j++)//必须先枚举这个
  29. for(int sta = 0; sta <= Lim; sta++)
  30. if(sta & (1 << j)) add(sum[i][sta], sum[i][sta ^ (1 << j)]);
  31. }
  32. int ans = 0;
  33. for(int i = 0; i <= Lim; i++) add(ans, f[N][i]);
  34. return ans;
  35. }
  36. int main() {
  37. int T = read();
  38. while(T--) printf("%d\n", solve());
  39. return 0;
  40. }
 友情链接:直通硅谷  点职佳  北美留学生论坛

本站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号