当前位置:   article > 正文

植物大战僵尸(pvz)_植物大战僵尸复杂度

植物大战僵尸复杂度

植物大战僵尸

题解

写这道题的过程贞德好艰辛呀。

很容易发现一个结论,如果我们把每个a_{i}转化\frac{1}{2^a{i}},如果所有的总和大于等于1,就一定有解。

因为如果这样的话,我们一定可以找出一种方法将两条路分成两个权值使得两边都不小于\frac{1}{2},除非你有一只僵尸跑到别人家里去了。而此时它肯定会选择其中一行全部消灭掉,我们还剩一行权值不小于\frac{1}{2},它们前进后得到的权值一定会不小于1,不断重复这个过程,我们就得到必胜的策略。

这样,第一个问题就解决了,我们接下来思考如何求出第一次策略的数量,就是将所有分成两个\frac{1}{2}的方案数。

考虑容斥,答案就是总方案数减去两个分出一个小于\frac{1}{2}的方案数。

我们可以定义dp_{i,j}表示到了第i个人这里,还差j2^a_{i}次方达到\frac{1}{2}。状态转移方程式也很好推,

dpi,j=dpi1,j2aiai1+dpi1,j+12iaai1

特别地,如果差的数量已经超过了剩余的数量,就不需要继续下去,直接加入答案,这样就只需要将dp_{i,j}的第二维减小到n了。

总的时间复杂度O\left(tn^2 \right )

源码

有些卡常。

  1. #include<cstdio>
  2. #include<cmath>
  3. #include<cstring>
  4. #include<iostream>
  5. #include<algorithm>
  6. #include<vector>
  7. #include<queue>
  8. using namespace std;
  9. #define MAXN 2005
  10. typedef long long LL;
  11. const int mo=1e9+7;
  12. const double eps=1e-7;
  13. typedef pair<int,int> pii;
  14. template<typename _T>
  15. _T Fabs(_T x){return x<0?-x:x;}
  16. template<typename _T>
  17. void read(_T &x){
  18. _T f=1;x=0;char s=getchar();
  19. while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
  20. while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
  21. x*=f;
  22. }
  23. int add(int x,int y){return x+y>=mo?x+y-mo:x+y;}
  24. int dp[MAXN][MAXN],n,a[MAXN],pow2[MAXN],t;
  25. double sum;
  26. signed main(){
  27. pow2[0]=1;for(int i=1;i<=2e3;i++)pow2[i]=2ll*pow2[i-1]%mo;read(t);
  28. while(t--){
  29. read(n);sum=0;int tmp=0;
  30. for(int i=1;i<=n;i++)read(a[i]),sum+=1.0/(1.0*pow2[a[i]]);
  31. if(sum<1.0-eps){puts("0");continue;}
  32. sort(a+1,a+n+1);dp[0][1]=1;a[0]=1;
  33. for(int i=1;i<=n;i++)
  34. for(int j=1;j<=n;j++){
  35. int tp=a[i]-a[i-1];if(j==((j>>tp)<<tp))dp[i][j]=dp[i-1][j>>tp];
  36. if(j+1==((j+1>>tp)<<tp))dp[i][j]=add(dp[i][j],dp[i-1][j+1>>tp]);
  37. if(j>(n-i))tmp=add(tmp,1ll*dp[i][j]*pow2[n-i]%mo),dp[i][j]=0;
  38. //printf("%d %d:%d %d\n",i,j,dp[i][j],dp[i-1][j/pow2[a[i]-a[i-1]]]);
  39. }
  40. int ans=(pow2[n]-tmp*2ll%mo+mo)%mo;printf("%d\n",ans);
  41. if(t>0)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)dp[i][j]=0;
  42. }
  43. return 0;
  44. }

谢谢!!!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/运维做开发/article/detail/920750
推荐阅读
相关标签
  

闽ICP备14008679号