[SDOI2019] 移动金币

题意:

一个$1\times n$的棋盘上最初摆放有m枚金币。其中每一枚金币占据了一个独立的格子,任意一个格子内最多只有一枚金币。

Alice 和 Bob 将要进行如下的一场游戏:二人轮流操作,且 Alice 先行。

当轮到一个玩家的时候,他可以选择一枚金币,并将其向左移动任意多格,且至少移动一格。金币不能被移出棋盘,也不能越过其它金币。

如果轮到一个玩家的时候他已经无法做出任何有效操作了(显然这个时候m枚金币恰好落在最左侧的m个格子中),则被判定为输家。

已经知道 Alice 和 Bob 都是极致聪明的人,他们在任何局面下总能做出最优的操作。那么有多少初始状态能保证 Alice 必胜呢?

$n\leq 150000,m\leq 50$。

 

题解:

将两个金币之间的距离视作物品,那么显然这是一个阶梯博弈,问题变为求出奇数阶梯异或和不为0的方案数。

转换一下,相当于把$n-m$个东西分成$m/2$份使得$a_{1}\bigoplus a_{2}\bigoplus\cdots\bigoplus a_{m/2}=0$。

直接背包是$O(mn^{2})$的,但我们注意到二进制位之间互相不影响,所以可以考虑逐位背包。

设$dp(i,j)$表示考虑二进制最高的i位,已经用了j个东西的方案数。转移时枚举第i位有多少a的二进制位为1。

$dp(i,j)=\sum \limits_{k=0,k\%2=0}^{m/2}{C_{m/2}^{k}\times dp(i+1,j-k(1<<i))}$

考虑完奇数阶梯后,偶数阶梯的位置已经定了,而阶梯上物品个数未定,于是利用插板法计算答案。

$ans=\sum \limits_{i=0}^{n-m}{C_{i+m/2-1}^{m/2-1}\times dp(0,n-m-i)}$

复杂度$O(nm\log{n})$。

 

套路:

  • 博弈论常见模型:巴什博弈,尼姆博弈,阶梯博弈,反尼姆博弈。
  • 二进制位之间互不影响的计数$\rightarrow$按二进制位逐位dp。

 

代码:

#include<bits/stdc++.h>
#define maxn 150005
#define maxm 55
#define inf 0x7fffffff
#define mod 1000000009
#define ll long long
#define rint register int
#define debug(x) cerr<<#x<<": "<<x<<endl
#define fgx cerr<<"--------------"<<endl
#define dgx cerr<<"=============="<<endl

using namespace std;
ll F[20][maxn],C[maxn][maxm];

inline ll read(){
    ll x=0,f=1; char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}

inline ll mo(ll x){return x>=mod?x-mod:x;}

int main(){
    int n=read(),m=read(),od=(m+1)/2,ov=m-od+1;
    if(n<=m){printf("0\n");return 0;} 
    int d=0; while((1<<d)<=n) d++; 
    F[d][0]=1,C[0][0]=1;
    for(rint i=1;i<=n;i++){
        C[i][0]=1;
        for(rint j=1;j<=min(i,m);j++) 
            C[i][j]=mo(C[i-1][j]+C[i-1][j-1]);
    }
    for(rint i=d-1;i>=0;i--)
        for(rint k=0;k<=od;k+=2)
            for(rint j=k*(1<<i);j<=n;j++)
                F[i][j]=mo(F[i][j]+C[od][k]*F[i+1][j-k*(1<<i)]%mod);
    ll ans=0;
    for(rint i=0;i<=n-m;i++)
        ans=mo(ans+C[i+ov-1][ov-1]*F[0][n-m-i]%mod);
    printf("%lld\n",mo(C[n][m]-ans+mod));
    return 0;
}
移动金币

 

posted @ 2020-06-12 14:30  Fugtemypt  阅读(271)  评论(0编辑  收藏  举报