zoukankan      html  css  js  c++  java
  • BZOJ4347 : [POI2016]Nim z utrudnieniem

    将石子从小到大排序,然后DP。

    设$f[i][j][k]$表示考虑了前$i$堆的石子,当前扔掉的堆数模$d$为$j$,没有扔掉的石子的异或和为$k$的方案数。

    因为石子排过序,所以转移的复杂度为$O(md)$。

    对于空间的问题,注意到$f[i][j][k]$和$f[i][j][k xor a[i]]$的转移是互补的,于是可以同时处理,省去滚动数组,直接做到原地DP,当然$f[i][0][k]$要特别处理。

    最后注意特判$n$是$d$的倍数的情况,此时答案应该减去$1$。

    #include<cstdio>
    const int N=1048576,P=1000000007;
    int n,d,m,p,i,j,k,x,a[N],f[10][N],g[N];
    inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
    inline int add(int a,int b){
      a+=b;
      if(a>=P)a-=P;
      return a;
    }
    int main(){
      for(read(n),read(d);i<n;i++){
        read(j),a[j]++;
        if(j>m)m=j;
      }
      for(f[0][0]=i=p=1;i<=m;i++){
        while(p<=i)p<<=1;
        while(a[i]--){
          for(k=0;k<p;k++)g[k]=add(f[d-1][k],f[0][k^i]);
          for(j=d-1;j;j--)for(k=0;k<p;k++)if(k<=(k^i)){
            x=f[j][k];
            f[j][k]=add(f[j-1][k],f[j][k^i]);
            f[j][k^i]=add(f[j-1][k^i],x);
          }
          for(k=0;k<p;k++)f[0][k]=g[k];
        }
      }
      return printf("%d",add(f[0][0],P-(n%d==0))),0;
    }
    

      

  • 相关阅读:
    Python报错:TypeError: data type not understood
    外星人入侵-01
    python界面编程
    python 之魔法方法
    软工第二次结对作业
    软工结对第一次作业
    软件工程第三次作业
    软件工程第二次作业
    我的第一篇博客
    python字符串的基本操作
  • 原文地址:https://www.cnblogs.com/clrs97/p/5006924.html
Copyright © 2011-2022 走看看