zoukankan      html  css  js  c++  java
  • BZOJ4550 小奇的博弈 【Nimk游戏 + dp + 组合数】

    题目

    这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色。最左边是白色棋子,最右边
    是黑色棋子,相邻的棋子颜色不同。
    这里写图片描述
    小奇可以移动白色棋子,提比可以移动黑色的棋子,它们每次操作可以移动1到d个棋子。每当移动某一个棋子时,
    这个棋子不能跨越两边的棋子,当然也不可以出界。当谁不可以操作时,谁就失败了。小奇和提比轮流操作,现在
    小奇先移动,有多少种初始棋子的布局会使它有必胜策略?

    输入格式

    共一行,三个数,n,k,d。对于100%的数据,有1<=d<=k<=n<=10000, k为偶数,k<=100。

    输出格式

    输出小奇胜利的方案总数。答案对1000000007取模。

    输入样例

    10 4 2

    输出样例

    182

    题解

    面对各种数学轰炸。。跪了。
    前置知识:
    Nimk游戏
    Nim游戏基础上,每次可以取之多d堆

    先手必败条件:每堆石子转成二进制,各个位的和都为(d + 1)的倍数
    例如可以取2次,石子数:111、101、110、011【二进制】
    每一位都有2+1=3个1,所以先手必败

    本题
    黑白棋子相间分布,白棋右移,黑棋左移,每对棋子的间隔长就相当于石子数,而每次可以操作d次,就相当于Nimk游戏

    求方案数
    一共有K/2堆石子,总数不超过N - K个
    首先,总的方案数为C(N,K),我们尝试求出必败的方案数,作差
    f[i][j]表示每堆石子的二进制表示中最高位为i位【从0开始算】,总共有j和石子的方案数
    那么有
    f[i+1][j+x(d+1)2i]+=f[i][j]C(K/2,x(D+1))

    原理:最高第i+1位的方案由最高第i位转移而来,每次同时加上(D+1)个1,可枚举x,表示加上x(D+1)来进行转移,而每次加入x(D+1)组石子,又有C(K/2,x(D+1))种方法

    【模型的转化,dp的应用,组合数的使用】

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define LL long long int
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define Redge(u) for (int k = h[u]; k != -1; k = ed[k].nxt)
    using namespace std;
    const int maxn = 10005,maxm = 105,INF = 1000000000,P = 1000000007;
    LL C[maxn][maxm],f[20][maxn];
    int main(){
        LL N,K,D;
        cin>>N>>K>>D;
        for (int i = 0; i <= N; i++){
            C[i][0] = 1;
            for (int j = 1; j <= i && j <= K; j++)
                C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % P;
        }
        f[0][0] = 1;
        for (LL i = 0; i <= 16; i++)
            for (LL j = 0; j <= N - K; j++)
                for (LL x = 0; x * (D + 1) <= K / 2 && x * (D + 1) * (1ll << i) + j <= N - K; x++)
                    f[i + 1][j + x * (D + 1) * (1ll << i)] = 
                    (f[i + 1][j + x * (D + 1) * (1ll << i)] + f[i][j] * C[K/2][x * (D + 1)]) % P;
        LL ans = C[N][K];
        for (int i = 0; i <= N - K; i++)
            ans = (ans - f[16][i] * C[N - K - i + K / 2][K / 2] % P) % P;
        cout<<(ans + P) % P<<endl;
        return 0;
    }
    
  • 相关阅读:
    PHP 大小写转换、首字母大写、每个单词首字母大写转换相关函数
    【论文学习4】BiSample: Bidirectional Sampling for Handling Missing Data with Local Differential Privacy
    【论文学习3】Local Differential Privacy for Deep Learning
    【论文学习2】 Differential Privacy Reinforcement Learning
    深度学习中的优化算法
    Spatial crowdsourcing
    “pip install tensorflow ”出现错误
    python或pip'不是内部或外部命令”
    pip install torch出现错误
    打不开gitHub的解决方法
  • 原文地址:https://www.cnblogs.com/Mychael/p/8282740.html
Copyright © 2011-2022 走看看