把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

【CF1628D2】Game on Sum (DP)

题目链接

  • 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;
}
posted @ 2022-03-03 20:58  TheLostWeak  阅读(52)  评论(0编辑  收藏  举报