题目链接

题意 : 给出 N 堆石子,每次可以选择一堆石子拿走任意颗石子,最后没有石子拿的人为败者。现在后手 Bob 可以在游戏开始前拿掉不超过 d 堆的整堆石子,现在问你有几种取走的组合使得 Bob 能保证他在游戏开始后是必胜的。

分析 :

在没有附加规则,即 Bob 可以先取走某些堆的情况下

就是个简单的 Nim 博弈模型,后手必胜当且仅当各个堆的石子的数目的异或和为 0

那么题目就变成了,问有多少种取走组合使得剩下的石子的异或和为 0

可以发现,可取走的石子的堆数 d 的上限不大,所以这个问题可以用 DP 解决

定义 dp[i][j][k] = 到第 i 堆石子为止,取走 j 堆石子,异或和为 k 的方案数有多少种

由于异或的自反性质,如果要从一个异或和集合中删除某个数,那么就相当于用这个数去异或这个集合的异或和

那么可以根据这个写出状态转移方程如下

dp[i][j][k] = dp[i-1][j][k] + dp[i-1][j-1][k^pile[i]]

意义为 当前的DP值可以从取了这堆石子就能将异或和变为 k 的状态转移而来

那么就要求从异或和 k 中删除 pile[i] ,即直接拿 k 去异或 pile[i] 即可

也因为由于有这个性质,设 pile[1]^pile[2]...^pile[n] 原所有石子的异或和为 aim

那么最后的答案就存在 dp[n][1~d][aim] 中,意义为 取出的石子的异或和为 aim 的话

那么相当于从还未被取走任何一堆石子的所有的异或和 aim 中取走 aim 那么剩下的异或和就为 0

所以答案在 dp[n][1~d][aim] 中,在写 DP 的时候注意模就行了

#include<bits/stdc++.h>
#define LL long long
#define ULL unsigned long long

#define scs(i) scanf("%s", i)
#define sci(i) scanf("%d", &i)
#define scd(i) scanf("%lf", &i)
#define scl(i) scanf("%lld", &i)
#define scIl(i) scanf("%I64d", &i)
#define scii(i, j) scanf("%d %d", &i, &j)
#define scdd(i, j) scanf("%lf %lf", &i, &j)
#define scll(i, j) scanf("%lld %lld", &i, &j)
#define scIll(i, j) scanf("%I64d %I64d", &i, &j)
#define sciii(i, j, k) scanf("%d %d %d", &i, &j, &k)
#define scddd(i, j, k) scanf("%lf %lf %lf", &i, &j, &k)
#define sclll(i, j, k) scanf("%lld %lld %lld", &i, &j, &k)
#define scIlll(i, j, k) scanf("%I64d %I64d %I64d", &i, &j, &k)

#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define lowbit(i) (i & (-i))
#define mem(i, j) memset(i, j, sizeof(i))

#define fir first
#define sec second
#define ins(i) insert(i)
#define pb(i) push_back(i)
#define pii pair<int, int>
#define mk(i, j) make_pair(i, j)
#define pll pair<long long, long long>
using namespace std;
 + ;
;
][maxn], arr[maxn];

int main(void)
{
    int nCase;
    sci(nCase);
    while(nCase--){
        int n, d;
        scii(n, d);
        d = min(d, n);

        , mx = ;
        ; i<=n; i++){
            sci(arr[i]);
            mx = max(arr[i], mx);
            aim ^= arr[i];
        }

        mem(dp, );
        ; i<=n; i++)
            dp[i][][arr[i]]++;

        ; i<=; i++)
            <<i) > mx){
                mx = (<<i);
                break;
            }

        ; i<=n; i++)
            ; j<=d; j++)
                ; k<=mx; k++)
                    dp[i][j][k] = (dp[i][j][k]%mod + (dp[i-][j][k] + dp[i-][j-][k^arr[i]])%mod)%mod;

        ) ?  : ;
        ; i<=d; i++)
            ans = (ans + dp[n][i][aim])%mod;

        printf("%d\n", ans);
    }
    ;
}

2018山东省赛 G Game ( Nim博弈 && DP )的更多相关文章

  1. 2018山东省赛sequence

    2018山东省赛sequence因为必须要删除一个数,所以可以计算每个数删除的代价,从而选取代价最小的进行删除如果一个数大于它前面的所有数的最小值而小于次小值,删除最小值的代价就要+1:如果一个数本身 ...

  2. 2016年省赛 G Triple Nim

    2016年省赛 G Triple Nimnim游戏,要求开始局面为先手必败,也就是异或和为0.如果n为奇数,二进制下最后一位只有两种可能1,1,1和1,0,0,显然异或和为1,所以方案数为0如果n为偶 ...

  3. 第八届河南省赛G.Interference Signal(dp)

    G.Interference Signal Time Limit: 2 Sec  Memory Limit: 128 MB Submit: 35  Solved: 17 [Submit][Status ...

  4. 2018山东省赛 H Dominoes ( 搜索 )

    题目链接 题意 : 给出一个 n * m 的矩阵,用规格 1 * 2 的多米诺去填充,题目数据保证最后只有一个格子是空白的(即没有被多米诺骨牌覆盖),问你现在通过移动多米诺能够产生多少种不同的状态(空 ...

  5. 2018山东省赛 E Sequence ( 思维 )

    题目链接 题意 : 给出一个排列,让你删除一个数,使得删除后整个序列的 Good 数数量最多.Good 数的定义为 若 Ai 为 Good 则存在 Aj < Ai ( j < i ) 分析 ...

  6. 2018 ACM 国际大学生程序设计竞赛上海大都会赛重现赛 J Beautiful Numbers (数位DP)

    2018 ACM 国际大学生程序设计竞赛上海大都会赛重现赛 J Beautiful Numbers (数位DP) 链接:https://ac.nowcoder.com/acm/contest/163/ ...

  7. 7.12 NOI模拟赛 探险队 期望 博弈 dp 最坏情况下最优策略 可并堆

    LINK:探险队 非常难的题目 考试的时候爆零了 完全没有想到到到底怎么做 (当时去刚一道数论题了. 首先考虑清楚一件事情 就是当前是知道整张地图的样子 但是不清楚到底哪条边断了. 所以我们要做的其实 ...

  8. 2018省赛赛第一次训练题解和ac代码

    第一次就去拉了点思维很神奇的CF题目 2018省赛赛第一次训练 # Origin Title     A CodeForces 607A Chain Reaction     B CodeForces ...

  9. zoj3591 Nim(Nim博弈)

    ZOJ 3591 Nim(Nim博弈) 题目意思是说有n堆石子,Alice只能从中选出连续的几堆来玩Nim博弈,现在问Alice想要获胜有多少种方法(即有多少种选择方式). 方法是这样的,由于Nim博 ...

随机推荐

  1. flaskurl传参用法

    from flask import Flask,request app = Flask(__name__) @app.route("/") def index(): return ...

  2. 文件的上传(1)(表单上传和ajax文件异步上传)

    文件的上传(表单上传和ajax文件异步上传) 项目中用户上传总是少不了的,下面就主要的列举一下表单上传和ajax上传!注意: context.Request.Files不适合对大文件进行操作,下面列举 ...

  3. HDU 2094 产生冠军(STL map)

    产生冠军 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  4. oracle ojdbc 版本须对应,否则日期字段查询结果与实际值可能不一致

    1. 数据库版本:select * from v$version; 2. 版本对应:

  5. Matcher和Pattern总结

    Matcher.Pattern简介 java.util.regex是一个用正则表达式所订制的模式来对字符串进行匹配工作的类库包.它包括两个类:Pattern和Matcher Pattern 一个Pat ...

  6. C++ Primer: 1. 初识输入和输出

    C++没有定义任何的输入和输出语句,而是使用了 标准库来提供IO机制---iostream; 标准库iostream定义了4种不同的IO对象: cin:     标准输入对象:instream类型的对 ...

  7. [HAOI2018]苹果树题解

    题目链接 大意:不解释 思路: 首先方案数共有n!种,第1个点只有1种选择,第2个点2种选择,生成2个选择的同时消耗一个,第3个点则有3种选择,依次类推共有n!种方案,由于最后答案*n!,故输出的实际 ...

  8. Forsaken喜欢数论

    链接:https://ac.nowcoder.com/acm/contest/1221/A来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 524288K,其他语言1048 ...

  9. 求x到y的最少计算次数 (BFS)

    时间限制:1秒 空间限制:262144K 给定两个-100到100的整数x和y,对x只能进行加1,减1,乘2操作,问最少对x进行几次操作能得到y? 例如:a=3,b=11: 可以通过3*2*2-1,3 ...

  10. 定位class时空格注意

    class属性中间的空格并不是空字符串,那是间隔符号,表示的是一个元素有多个class的属性名称,那定位的时候取其中的一个就行(并且要唯一) Selenium2+python自动化73-定位的坑:cl ...