考虑dp,dp(n, m)表示还有n步操作,Bob至少还需要进行m步add操作的最终答案。
则假设当前Alice选择了一个x(x belong to [0, k]),那么Bob有两种走法:(假设当前不在边界情况)
1) 用减, 则答案为dp(n - 1, m) - x
2) 用加, 则答案为dp(n - 1, m - 1) + x
注意到dp(n - 1, m) > dp(n - 1, m - 1)
因此可以分别画出dp(n - 1, m) - x 和dp(n - 1, m - 1) + x的图像,则是一个"X”型,显然Alice会选择交点的那个x值,则发现dp(n, m) = (dp(n - 1, m) + dp(n - 1, m - 1)) / 2
考虑边界情况,dp(i, 0) = 0, dp(i, i) = k * i
之后考虑令f(n, m) = dp(n, m) * (2 ^ n) ,把n看成x轴、m看成y轴,发现f(n, m)的转移相当于要么往左下(-1,-1)方向走,要么往左(-1,0)走,然后考虑反方向推,即考虑从各个边界位置走到(n, m)方案,则因为dp(i, 0) = 0不用考虑,只用考虑(i, i)向右上或者向右,且不经过其它边界点,走到(n, m)方案数,发现此时相当于第一步一定要向右走,之后向右上或者向右任意,故减去第一步后总共需要走(n - i - 1) 步,其中(m - i)步要是右上方,得到此时贡献即为 C(n - i - 1, m - i)
下面的代码是之前用另一种奇奇怪怪的方法推的,不过也差不多
#include<bits/stdc++.h>
#define pii pair<int,int>
#define fi first
#define sc second
#define pb push_back
#define ll long long
#define trav(v,x) for(auto v:x)
#define all(x) (x).begin(), (x).end()
#define VI vector<int>
#define VLL vector<ll>
#define pll pair<ll, ll>
#define double long double
//#define int long long
using namespace std;
const int N = 2e6 + 100;
const int inf = 1e9;
//const ll inf = 1e18;
const ll mod = 1e9 + 7;
#ifdef LOCAL
void debug_out(){cerr << endl;}
template<typename Head, typename... Tail>
void debug_out(Head H, Tail... T)
{
cerr << " " << to_string(H);
debug_out(T...);
}
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif
ll fac[N], pw[N], ifac[N], ipw[N];;
ll qpow(ll x, ll y = mod - 2)
{
ll res = 1;
while(y)
{
if(y & 1)
res = res * x % mod;
x = x * x % mod;
y >>= 1;
}
return res;
}
void init()
{
int n = 2e6;
fac[0] = 1;
for(int i = 1; i <= n; i++)
fac[i] = fac[i - 1] * i % mod;
ifac[n] = qpow(fac[n]);
for(int i = n - 1; i >= 0; i--)
ifac[i] = ifac[i + 1] * (i + 1) % mod;
pw[0] = 1;
for(int i = 1; i <= n; i++)
pw[i] = pw[i - 1] * 2 % mod;
ipw[0] = 1;
for(int i = 1; i <= n; i++)
ipw[i] = ipw[i - 1] * (ll)(5e8 + 4) % mod;
}
ll C(ll x, ll y)
{
if(x < y)
return 0;
if(y < 0)
return 0;
return fac[x] * ifac[y] % mod * ifac[x - y] % mod;
}
void sol()
{
int n, m, k;
cin >> n >> m >> k;
ll ban = 0, ans = 0;
for(int i = 1; i <= m; i++)
{
ll val = i * 2 - 1;
ll coef = C(n - 1, m - i);
//cerr << val << ' ' << coef << '\n';
ans = (ans + val * coef) % mod;
}
cout << ans * k % mod * ipw[n - 1] % mod << '\n';
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
init();
int tt;
cin >> tt;
while(tt--)
sol();
}