【题解 CF1628D2】 Game on Sum

Game on Sum (Hard Version)

题面翻译

Alice 和 Bob 正在玩一个游戏,游戏分为 \(n\) 个回合,Alice 和 Bob 要轮流对一个数 \(x\) 进行操作,已知这个数初始值是 \(0\)

具体每个回合的行动规则如下:

  1. Alice 选择一个在区间 \([0,k]\) 之间的实数 \(t\)
  2. Bob 可以选择让 \(x\) 变成 \(x+t\) 或者 \(x-t\),但是 Bob 在 \(n\) 个回合之内至少选择 \(m\) 次让 \(x\) 变成 \(x+t\)

Alice想让最终的 \(x\) 最大,Bob 想让最终的 \(x\) 最小。

已知双方均采用最优策略,求最终的 \(x\) 值(对 \(10^9+7\) 取模)。

数据范围保证:\(1\le m\le n\le 10^6,k\le10^9+7\)\(\sum\limits n\leq10^6\)

题目描述

This is the hard version of the problem. The difference is the constraints on $ n $ , $ m $ and $ t $ . You can make hacks only if all versions of the problem are solved.

Alice and Bob are given the numbers $ n $ , $ m $ and $ k $ , and play a game as follows:

The game has a score that Alice tries to maximize, and Bob tries to minimize. The score is initially $ 0 $ . The game consists of $ n $ turns. Each turn, Alice picks a real number from $ 0 $ to $ k $ (inclusive) which Bob either adds to or subtracts from the score of the game. But throughout the game, Bob has to choose to add at least $ m $ out of the $ n $ turns.

Bob gets to know which number Alice picked before deciding whether to add or subtract the number from the score, and Alice gets to know whether Bob added or subtracted the number for the previous turn before picking the number for the current turn (except on the first turn since there was no previous turn).

If Alice and Bob play optimally, what will the final score of the game be?

输入格式

The first line of the input contains a single integer $ t $ ( $ 1 \le t \le 10^5 $ ) — the number of test cases. The description of test cases follows.

Each test case consists of a single line containing the three integers, $ n $ , $ m $ , and $ k $ ( $ 1 \le m \le n \le 10^6, 0 \le k < 10^9 + 7 $ ) — the number of turns, how many of those turns Bob has to add, and the biggest number Alice can choose, respectively.

It is guaranteed that the sum of $ n $ over all test cases does not exceed $ 10^6 $ .

输出格式

For each test case output a single integer number — the score of the optimal game modulo $ 10^9 + 7 $ .

Formally, let $ M = 10^9 + 7 $ . It can be shown that the answer can be expressed as an irreducible fraction $ \frac{p}{q} $ , where $ p $ and $ q $ are integers and $ q \not \equiv 0 \pmod{M} $ . Output the integer equal to $ p \cdot q^{-1} \bmod M $ . In other words, output such an integer $ x $ that $ 0 \le x < M $ and $ x \cdot q \equiv p \pmod{M} $ .

样例 #1

样例输入 #1

7
3 3 2
2 1 10
6 3 10
6 4 10
100 1 1
4 4 0
69 4 20

样例输出 #1

6
5
375000012
500000026
958557139
0
49735962

提示

In the first test case, the entire game has $ 3 $ turns, and since $ m = 3 $ , Bob has to add in each of them. Therefore Alice should pick the biggest number she can, which is $ k = 2 $ , every turn.

In the third test case, Alice has a strategy to guarantee a score of $ \frac{75}{8} \equiv 375000012 \pmod{10^9 + 7} $ .

In the fourth test case, Alice has a strategy to guarantee a score of $ \frac{45}{2} \equiv 500000026 \pmod{10^9 + 7} $ .

解题思路

我们先思考用 \(DP\) 来解决这道题。
我们可以设 \(f_{i,j}\) ,表示已进行了 \(i\) 次,其中 \(j\) 次是加运算,但是因为博弈论,每个 \(f_{i,j}\) 只基于后面的决策,而且一般概率 \(DP\) 是从前往后考虑的,所应把 \(f_{i,j}\) 设为还剩下 \(i\) 次未进行,还未加 \(j\) 次。
边界条件即为 \(f_{i,i}=i \times k\)
转移方程即为 \(f_{i,j}=min(f_{i+1,j}-x,f_{i+1,j-1}+x)\) ,当 \(x=\frac{f_{i+1,j}-f_{i+1,j-1}}{2}\)\(f_{i,j}\) 取最大值,所以 \(f_{i,j} =\frac{f_{i+1,j}+f_{i+1,j-1}}{2}\)
这样就有了 \(nm\) 的做法了。
要拿 \(100\) ,我们需要思考这个 \(DP\) 的本质。
对于每一个 \(f_{i,i}\) ,思考他对答案的贡献,它走到答案即为 \(k\) 乘上路径条数再除以若干次 \(2\)
因为 \(f_{i,i}\) 不能走到 \(f_{i+1,i+1}\),路径条数即为 \(f_{i+1,i}\) 走到 \(f_{n,m}\) 的条数,而除以 \(2\) 的次数即为 \(n-i\) ,所以答案为 \(k \times \sum_{i = 1}^{m} \frac{i \times C_{n-i-1}^{m-1}}{2^{n-i}}\)
特判 \(n=m\) 的情况,时间复杂度 \(O(nlogn)\)

Code

#include<bits/stdc++.h>
using namespace std;
const long long mod=1e9+7;
long long n,m,k,f[1000005];
long long dijah(long long x,long long y)
{
	long long h=1;
	while(y)
	{
		if(y&1)
		{
			h*=x;
			h%=mod;
		}
		x*=x;
		x%=mod;
		y>>=1;
	}
	return h;
}
long long C(long long x,long long y)
{
	return (f[x]*dijah(f[x-y],mod-2)%mod)*dijah(f[y],mod-2)%mod;
}
void qer()
{
	scanf("%lld%lld%lld",&n,&m,&k);
	if(n==m)
	{
		printf("%lld\n",m*k%mod);
		return;
	}
	long long s=0;
	for(int i=1;i<=m;i++)
	{
		s+=(C(n-i-1,m-i)*i%mod)*dijah(dijah(2,mod-2),n-i)%mod;
		s%=mod;
	}
	printf("%lld\n",(s*k)%mod);
	return;
} 
int main()
{
	long long qwe;
	f[0]=1;
	for(int i=1;i<=1000000;i++)f[i]=f[i-1]*i%mod;
	scanf("%lld",&qwe);
	for(int i=1;i<=qwe;i++)qer();








  return 0;
}

posted @ 2023-11-17 10:18  dijah  阅读(50)  评论(0编辑  收藏  举报