Game on sum(easy+hard)

· · 题解

博弈论 dp 好题。

博弈论 dp 通常都是从终止态开始往前 dp。
首先还是找关键词——我们用什么刻画一个子游戏——Bob 还剩几个加法要做、游戏(还剩)的轮数。

f(i,j) 表示还剩 i 轮,Bob 还剩 j 个加法要做,聪明的 Alice 在这一轮中能把自己引向的最大局面的值。

f(i,j)=\max_{x\in[0,k]}\{\min(f(i-1,j-1)+x,\min(f(i-1,j)-x\}

由于根据常识 f(i-1,j)\ge f(i-1,j-1) 而两者都是定值,所以当且仅当 x=\frac{f(i-1,j)-f(i-1,j-1)}2 时,f(i,j) 取到最大值 \frac{f(i-1,j)+f(i-1,j-1)}2

i=j 时,只能够从 f(i-1,j-1) 转移,并且不难发现 f(i,i)=i\times k

这个 O(nm) 的 dp 足以解决 Easy Version。

由于 dp 数组的每一个位置都可看作关于 dp 边界值的函数,所以我们考虑每一个 dp 边界值(f(i,i))对于 f(n,m) 的贡献。

$$f(n,m)=\sum_{i=1}^n\frac {n-i-1\choose m-i}{2^{n-i}}\cdot i\times k$$ ```cpp #include <bits/stdc++.h> using namespace std; inline int read(){ register char ch=getchar();register int x=0; while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); return x; } const int N=1e6+5,mod=1e9+7,I2=(mod+1)/2; int n,m,K,jc[N],ijc[N],miI2[N]; int C(int n,int m){return 1ll*jc[n]*ijc[m]%mod*ijc[n-m]%mod;} void add(int &x,int y){(x+=y)>=mod&&(x-=mod);} inline int qp(int a,int b){int c=1;for(;b;b>>=1,a=1ll*a*a%mod)if(b&1)c=1ll*c*a%mod;return c;} void solve(){ n=read(),m=read(),K=read(); jc[0]=ijc[0]=1;for(int i=1;i<=n;i++)jc[i]=1ll*jc[i-1]*i%mod; ijc[n]=qp(jc[n],mod-2); for(int i=n-1;i;i--)ijc[i]=1ll*ijc[i+1]*(i+1)%mod; miI2[0]=1;for(int i=1;i<=n;i++)miI2[i]=1ll*miI2[i-1]*I2%mod; if(n==m){cout<<1ll*n*K%mod<<'\n';return;} int ans=0; for(int i=1;i<=min(m,n-1);i++)add(ans,1ll*C(n-i-1,m-i)*miI2[n-i]%mod*i%mod*K%mod); cout<<ans<<'\n'; } int main(){ int T=read(); while(T--)solve(); } ```