t题目链接:
Problem - 2271B - Codeforces
最佳思路:
#include<bits/stdc++.h> using namespace std; int main() { int t; cin >> t; while (t--) { int n, k; cin >> n >> k; vector<int> arr(n + 1); while (n--) { int x; cin >> x; arr[x]++; } int flag = 1; for (int i = 0; i < (int)arr.size(); i++) { if (arr[i] >= 2 * k) continue; if (arr[i] == 2 * k - 1) { cout << "YES" << endl; flag = 0; } break; } if (flag == 1) cout << "NO" << endl; } }核心思路:
如果考虑先手怎么去赢,可能会有点复杂
不如思考后手怎么赢,也就是需要与对手“打平”: 对于每一个数字的出现次数,双方都应该:
要么都小于k,要么都大于k
这样保证双方数组的“状态”是一样的
双方的最佳策略就是模仿对手的行动,防止对手单一积累某一个数打破平衡
只要每个数出现次数大于等于2k 就意味着对输赢没有影响 因为双方可以依次拿走一半,同时都大于等于k,那么这个数字的出现次数对输赢无影响
小于2k时:
如果小于等于2k-2 也没影响 因为双方依次拿,都拿不够k
如果等于2k - 1 出现转折点:
一人拿够了 一人没拿够,这时先手的就赢,因为这个数字的出现次数打破了“平衡”
之后对每个数字的位数进行遍历,只要有一个数字的位数打破平衡,那就直接可以决定胜负