[AGC056D] Subset Sum Game
[AGC056D] Subset Sum Game
题面翻译
一块黑板上写着 \(n\) 个整数。第 \(i\) 个整数记作 \(a_i\)。保证 \(n\) 是偶数。此外,给定 \(L,R\)。
Alice 和 Bob 在玩一个游戏。他们轮流操作,Alice 先手。在每一轮中,玩家需要选择一个写在黑板上的数,并擦掉它。
游戏会在 \(n\) 轮后结束。令 \(s\) 为 Alice 擦掉的数之和。若 \(L \le s \le R\),则 Alice 胜利,反之 Bob 胜利。你需要输出当两方都采取最优策略情况下的赢家。
\(2\le n\le 5000,\ 1\le a_i\le 10^9, 0\le L \le R \le \sum_{1\le i\le n} a_i\)。
题目描述
黒板に $ N $ 個の整数が書かれており,そのうち $ i $ 番目の整数は $ A_i $ です. なお,$ N $ は偶数です. また,整数 $ L,R $ が与えられます.
Alice と Bob がゲームをします. 二人は Alice からはじめて交互に手番をプレイします. 各手番では,プレイヤーは黒板に書かれている数を一つ選んで消します.
$ N $ ターン後にゲームが終了します. ここで,Alice が消した整数の総和を $ s $ とします. $ L\ \leq\ s\ \leq\ R $ であれば Alice の勝利,そうでなければ Bob の勝利です. 両者が最適に行動した時,どちらが勝つか求めてください.
输入格式
入力は以下の形式で標準入力から与えられる.
$ N $ $ L $ $ R $ $ A_1 $ $ A_2 $ $ \cdots $ $ A_N $
输出格式
Alice が勝つ場合は Alice
,Bob が勝つ場合は Bob
と出力せよ.
样例 #1
样例输入 #1
4 5 6
3 1 4 5
样例输出 #1
Alice
样例 #2
样例输入 #2
2 2 3
4 1
样例输出 #2
Bob
样例 #3
样例输入 #3
30 655 688
42 95 9 13 91 27 99 56 64 15 3 11 5 16 85 3 62 100 64 79 1 70 8 69 70 28 78 4 33 12
样例输出 #3
Bob
样例 #4
样例输入 #4
30 792 826
81 60 86 57 5 20 26 13 39 64 89 58 43 98 50 79 58 21 27 68 46 47 45 85 88 5 82 90 74 57
样例输出 #4
Alice
提示
制約
- $ 2\ \leq\ N\ \leq\ 5000 $
- $ N $ は偶数
- $ 1\ \leq\ A_i\ \leq\ 10^9 $
- $ 0\ \leq\ L\ \leq\ R\ \leq\ \sum_{1\ \leq\ i\ \leq\ N}\ A_i $
- 入力される値はすべて整数である
Sample Explanation 1
このゲームでは Alice が必ず勝ちます. ゲームの進行の一例を以下に示します. - Alice が $ 1 $ を消す. - Bob が $ 4 $ を消す. - Alice が $ 5 $ を消す. - Bob が $ 3 $ を消す. この時,Alice が消した整数の総和は $ 6 $ であり,$ L\ \leq\ 6\ \leq\ R $ なので,Alice の勝利です.
这题是道博弈论黑题,看似毫无落脚点,那我们首先转移题意,设\(S_a\)为\(Alice\)擦掉的总数和,\(S_b\)为\(Bob\)擦掉的总数和,设\(S\)为所有数的和。题目要求\(L<=S_a<=R\)
那我们可以转换为\(2L<=2S_a<=2R\)
\(2L-S<=2S_a-S<=2R-S\)
\(2L-S<=S_A-S_B<=2R-S\)
设\(x=S-(L+R)\)
则原式为\(L-R<=S_a-S_B+x<=R-L\)即为\(|S_a-S_B+x|<=R-L\)
这时候,题意就转换完了
题意转换为,给定整数\(x\),\(Alice\)一次操作,使得\(x'=S-(R+L-a_i)=x+a_i\),则\(Bob\)为\(X-a_i\)
但\(Alice\)想让\(x\)尽量小,\(Bob\)想让\(x\)尽量大,问谁赢?
记一个长为\(m\)序列\(b_i\)的相邻项差分\(diffb=(b_2-b_1)+(b_4-b_3)+...+(b_m-b_{m-1})\)
假设\(a_i\)升序排列。推断,最终的分数可以通过如下方式求得:
- 选择整数\(p\),将\(p,p+x,a_1,a_2,...,a_n\)升序得到\(A_i\),令\(p\)的答案为\(diff A\)的值
- 最终的分数即为所有可能的\(p\)的答案中的最小值
复杂度为\(O(n^2)\)
点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define lid (rt<<1)
#define rid (rt<<1|1)
#define endl '\n'
//#define int long long
#define pb push_back
using namespace std;
const int N = 5005;
ll n,l,r,a[N];
int main()
{
speed();
int T;
cin>>T;
// T=1;
while(T--)
{
cin>>n>>l>>r;
ll s=0;
for(int i=1;i<=n;i++)cin>>a[i],s+=a[i];
s-=(l+r);
sort(a+1,a+1+n);
vector <ll> p;
ll ans=LLONG_MAX;
for(int i=1;i<=n;i++)
{
ll tmp=0;
p.clear();
for(int j=1;j<=n;j++)
{
if(i==j)continue;
p.pb(a[j]);
}
p.insert(lower_bound(p.begin(),p.end(),a[i]+s),a[i]+s);
for(int i=n-1;i>=0;i-=2)tmp+=(p[i]-p[i-1]);
ans=min(ans,abs(tmp));
}
// cout<<abs(ans)<<endl;
if(abs(ans)<=r-l)cout<<"Alice"<<endl;
else cout<<"Bob"<<endl;
}
return 0;
}