zoukankan      html  css  js  c++  java
  • BZOJ4347 POI2016Nim z utrudnieniem(博弈+动态规划)

      由nim游戏的结论,显然等价于去掉一些数使剩下的数异或和为0。

      暴力的dp比较显然,设f[i][j][k]为前i堆移走j堆(模意义下)后异或和为k的方案数。注意到总石子数量不超过1e7,按ai从小到大排序,这样k的枚举范围就不会超过2ai,于是复杂度O(md)。

      注意空间卡的非常紧,连滚动都开不下,改为留下的有j堆(模意义下)可能比较方便,存一下j=d-1时的数组,对j=1~d-1倒序转移完后再特判j=0即可。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 500010
    #define P 1000000007
    int n,m,a[N],u[N<<1],f[10][1<<20],tmp[1<<20];
    inline void inc(int &x,int y){x+=y;if (x>=P) x-=P;}
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj4347.in","r",stdin);
        freopen("bzoj4347.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),m=read();
        for (int i=1;i<=n;i++) a[i]=read();
        sort(a+1,a+n+1);
        int t=1;
        for (int i=1;i<=1000000;i++)
        {
            if (t<i) t=t<<1|1;
            u[i]=t;
        }
        f[0][0]=1;
        for (int i=1;i<=n;i++)
        {
            memcpy(tmp,f[m-1],u[a[i]]+1<<2);
            for (int j=m-1;j>=1;j--)
                for (int k=0;k<=u[a[i]];k++)
                inc(f[j][k],f[j-1][k^a[i]]);
            for (int k=0;k<=u[a[i]];k++)
            inc(f[0][k],tmp[k^a[i]]);
        }
        cout<<(f[n%m][0]-(n%m==0)+P)%P;
        return 0;
    }
  • 相关阅读:
    关于浏览器及系统的判断
    toggle与slideToggle
    安卓与ios的不同处理
    关于常用循环遍历获取数据
    docker
    Mysql
    rabbitMQ的使用转载
    Git命令行
    vue项目创建完整版
    redis操作(str.hash.list.set)
  • 原文地址:https://www.cnblogs.com/Gloid/p/9862313.html
Copyright © 2011-2022 走看看