Codeforces 1629 F1. Game on Sum (Easy Version) —— DP,博弈,思维

This way

题意:

你手上有一个数字,一开始是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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值