题意:
你手上有一个数字,一开始是0,每次可以选择[0,k]中任意一个实数。然后由对手决定加还是减去这个数字。总共n轮,并且对手至少要有m轮加上你手中的数字。你希望数字尽可能大,对手希望数字尽可能小。如果你们双方都做出最优抉择,问数字最大是多少。
题解:
博弈…我是真的菜。那个2000左右的博弈就能把我按在地上摩擦,还是得多练练
我一开始还想顺着做,连样例都模不出来QAQ。
那么设dp[n][m]为当前总共要拿n轮,对手至少要加m轮。
拿拿了一轮以后,由于前面的决策并不影响后面的情况,所以要么变成dp[n-1][m],要么变成dp[n-1][m-1]。
假设当前这一轮拿的值是x。那么总共有两种情况:
1.dp[n-1][m-1]+x
2.dp[n-1][m]-x
对手会拿哪个?当然是最小那个min(dp[n-1][m-1]+x,dp[n-1][m]-x)。
如何将这个值变得尽可能大?当x=(dp[n-1][m-1]+dp[n-1][m])/2的时候。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod=1e9+7;
const int N=2e3+5;
ll dp[N][N];
ll qpow(ll a,ll b){ll ans=1;for(;b;a=a*a%mod,b>>=1)if(b&1)ans=ans*a%mod;return ans;}
int main()
{
int inv=qpow(2,mod-2);
for(int i=1;i<N;i++)dp[i][i]=i;
for(int i=2;i<N;i++)
for(int j=1;j<i;j++)
dp[i][j]=(dp[i-1][j]+dp[i-1][j-1])*inv%mod;
int t;
scanf("%d",&t);
while(t--){
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
printf("%lld\n",dp[n][m]*k%mod);
}
return 0;
}