题意:
解法:
d[i][j]表示一共i轮,B需要执行j次加操作,这种子游戏局面下,A能获得的最大值。
对于子游戏d[i][j],设A选的数是x
如果B选择加,则结果为d[i-1][j-1]+x
如果B选择减,则结果为d[i-1][j]-x
由于B要使d[i][j]尽量小,则对于当前游戏的最优解为:
d[i][j]=min(d[i-1][j-1]+x,d[i-1][j]-x);
由于A要使d[i][j]尽量大,即min(d[i-1][j-1]+x,d[i-1][j]-x)尽量大,
由于左侧随x的增大而增大,右侧随x的增大而减小
因此x在d[i-1][j-1]+x=d[i-1][j]-x时,值最大
此时x=(d[i-1][j]-d[i-1][j-1])/2
且d[i][j]=(d[i-1][j]+d[i-1][j-1])/2
转移方程总结:
当i-1>=j时, B可选择是否使用加操作:
d[i][j]=(d[i-1][j-1]+d[i-1][j])/2
否则说明B不得不使用加操作:
d[i][j]=d[i-1][j-1]+k
Code:
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define int long long
#define PI pair<int, int>
const int maxm=5e5+5;
const int mod=1e9+7;
int n,m,k;
int d[2222][2222];
int ppow(int a,int b,int mod){
int ans=1%mod;a%=mod;
while(b){
if(b&1)ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
void solve(){
cin>>n>>m>>k;
int inv2=ppow(2,mod-2,mod);
for(int i=1;i<=n;i++){
for(int j=1;j<=m&&j<=i;j++){
if(i-1>=j){
d[i][j]=(d[i-1][j-1]+d[i-1][j])*inv2%mod;
} else {
d[i][j]=(d[i-1][j-1]+k)%mod;
}
}
}
int ans=d[n][m];
ans=(ans%mod+mod)%mod;
cout<<ans<<endl;
}
signed main() {
#define MULTI_CASE
ios::sync_with_stdio(0);
cin.tie(0);
#ifndef ONLINE_JUDGE
freopen("../in.txt", "r", stdin);
freopen("../out.txt", "w", stdout);
#endif
#ifdef MULTI_CASE
int T;
cin >> T;
while (T--)
#endif
solve();
return 0;
}