- A 和 B 会进行 \(n\) 轮游戏,初始计数器 \(t=0\)。
- 每轮 A 会先选择一个数 \(x\in[0,k]\),然后 B 选择给 \(t\) 减去 \(x\) 或加上 \(x\),且总共至少需要选择 \(m\) 次给 \(t\) 加上 \(x\)。
- A 想要最大化 \(t\),B 想要最小化 \(t\),求两人都选择最优策略时最终的 \(t\)。
- \(1\le m\le n\le10^6\)
暴力动态规划
设 \(f_{n,m}\) 表示局面 \((n,m)\) 的答案。
假设 A 第一步选择了数 \(x\),则 B 有两种选择:减 \(x\),进入局面 \((n-1,m)\);加 \(x\),进入局面 \((n-1,m-1)\)。
即 \(f_{n,m}=\max_x\{\min\{f_{n-1,m}-x,f_{n-1,m-1}+x\}\}\),那么肯定取 \(f_{n,m}=\frac{f_{n-1,m}+f_{n-1,m-1}}2\)。
注意,当 \(n=m\) 的时候,B 只能一直选择加 \(x\),即 \(f_{n,n}=nk\)。
优化
给 \(f_{n,m}=\frac{f_{n-1,m}+f_{n-1,m-1}}2\) 两边同时乘以 \(2^n\),得到:
\[2^nf_{n,m}=2^{n-1}f_{n-1,m}+2^{n-1}f_{n-1,m-1}
\]
所以设 \(g_{n,m}=2^nf_{n,m}\),就有:
\[g_{n,m}=g_{n-1,m}+g_{n-1,m-1}
\]
这个转移和组合数完全相同。
而我们需要特殊考虑的只有 \(n=m\) 的 \(m\) 种情况,只要枚举第一次选择向右而不向右上方走的位置 \((i,i)\),给 \(g_{i,i}\) (即 \(2^iik\))乘上 \((i+1,i)\) 走到 \((n,m)\) 的方案数(即 \(C_{n-i-1}^{m-i}\))转移即可。
代码:\(O(n)\)
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Rg register
#define RI Rg int
#define Cn const
#define CI Cn int&
#define I inline
#define W while
#define N 1000000
#define X 1000000007
#define C(x,y) (1LL*Fc[x]*Ic[y]%X*Ic[(x)-(y)]%X)
using namespace std;
int n,m,k,Fc[N+5],Ic[N+5];
I int QP(RI x,RI y) {RI t=1;W(y) y&1&&(t=1LL*t*x%X),x=1LL*x*x%X,y>>=1;return t;}
int main()
{
RI i;for(Fc[0]=i=1;i<=N;++i) Fc[i]=1LL*Fc[i-1]*i%X;for(Ic[i=N]=QP(Fc[N],X-2);i;--i) Ic[i-1]=1LL*Ic[i]*i%X;
RI Tt,p,t;scanf("%d",&Tt);W(Tt--)
{
if(scanf("%d%d%d",&n,&m,&k),n==m) {printf("%d\n",(int)(1LL*n*k%X));continue;}//特判n=m
for(p=1,t=i=0;i<=min(i,m);p=2*p%X,++i) t=(t+1LL*p*i%X*k%X*C(n-i-1,m-i))%X;//枚举第一个向右走的位置
printf("%d\n",(int)(1LL*t*QP(2,X-1-n)%X));//除以2^n
}return 0;
}