前情提要:这场全是思维题,一点算法没有,所以脑子好就能上分。但是个人认为这种场没有啥意义,所以t宝不会出题,下次别出了。(狗头保命)
目录
A. Card Exchange:
题目大意:
思路解析:
这个题说的就是你有n张牌,每个牌有个数字,你可以选择数字相同的k张牌,然后将其改变为k-1张牌,并且改变后的牌上的数字是任意的。那么可以发现只要我有个数字的牌超过k张,那么我可以一直让k-1这个牌的颜色不变,直到这个数字的牌只有k张,然后我可以将这个k张牌改变为其他颜色的牌,(然后将这个颜色变为k张)那么可以发现最后一定会剩k-1张,如果没有一张颜色的牌的数量超过k张,那么一定会剩n张。
代码实现:
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
int t = f.nextInt();
while (t > 0) {
solve();
t--;
}
w.flush();
w.close();
}
static int mod = 998244353;
static int inf = (int) 1e9;
public static void solve() throws IOException {
int n = f.nextInt(); int k = f.nextInt();
int[] cnt = new int[10000];
boolean st = false;
for (int i = 0; i < n; i++) {
int num = f.nextInt();
cnt[num]++;
if (cnt[num] >= k) st = true;
}
if (st) w.println(k - 1);
else w.println(n);
}
public static void swap(int[] a, int i, int j) {
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
public static long qkm(long a, long b, long mod) {
long res = 1;
while (b > 0) {
if ((b & 1) == 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
public static class Pair {
int x, y, val;
public Pair(int ne, int val, int x) {
this.x = ne;
this.y = val;
this.val = x;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Pair pair = (Pair) o;
return x == pair.x && y == pair.y;
}
@Override
public int hashCode() {
return Objects.hash(x, y);
}
}
public static class Node {
int x, y;
public Node(int x, int y) {
this.x = x;
this.y = y;
}
}
static PrintWriter w = new PrintWriter(new OutputStreamWriter(System.out));
static Input f = new Input(System.in);
static class Input {
public BufferedReader reader;
public StringTokenizer tokenizer;
public Input(InputStream stream) {
reader = new BufferedReader(new InputStreamReader(stream), 32768);
tokenizer = null;
}
public String next() throws IOException {
while (tokenizer == null || !tokenizer.hasMoreTokens()) {
tokenizer = new StringTokenizer(reader.readLine());
}
return tokenizer.nextToken();
}
public String nextLine() throws IOException {
String str = null;
str = reader.readLine();
return str;
}
public int nextInt() throws IOException {
return Integer.parseInt(next());
}
public long nextLong() throws IOException {
return Long.parseLong(next());
}
public Double nextDouble() throws IOException {
return Double.parseDouble(next());
}
}
}
B. Rectangle Filling:
题目大意:
思路解析:
可以发现只要四个边都有某个颜色,那么就可以满足题目要求。
代码实现:
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
int t = f.nextInt();
while (t > 0) {
solve();
t--;
}
w.flush();
w.close();
}
static int mod = 998244353;
static int inf = (int) 1e9;
public static void solve() throws IOException {
int n = f.nextInt(); int m = f.nextInt();
char[][] map = new char[n][m];
for (int i = 0; i < n; i++) {
map[i] = f.next().toCharArray();
}
boolean a1 = false; boolean a2 = false;
boolean b1 = false; boolean b2 = false;
boolean c1 = false; boolean c2 = false;
boolean d1 = false; boolean d2 = false;
for (int i = 0; i < m; i++) {
if (map[0][i] == 'W') a1 = true;
if (map[0][i] == 'B') a2 = true;
}
for (int i = 0; i < m; i++) {
if (map[n-1][i] == 'W') b1 = true;
if (map[n-1][i] == 'B') b2 = true;
}
for (int i = 0; i < n; i++) {
if (map[i][0] == 'W') c1 = true;
if (map[i][0] == 'B') c2 = true;
}
for (int i = 0; i < n; i++) {
if (map[i][m-1] == 'W') d1 = true;
if (map[i][m-1] == 'B') d2 = true;
}
if ((a1 && c1 && b1 && d1) || (a2 && b2 && c2 && d2)) w.println("YES");
else w.println("NO");
}
public static void swap(int[] a, int i, int j) {
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
public static long qkm(long a, long b, long mod) {
long res = 1;
while (b > 0) {
if ((b & 1) == 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
public static class Pair {
int x, y, val;
public Pair(int ne, int val, int x) {
this.x = ne;
this.y = val;
this.val = x;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Pair pair = (Pair) o;
return x == pair.x && y == pair.y;
}
@Override
public int hashCode() {
return Objects.hash(x, y);
}
}
public static class Node {
int x, y;
public Node(int x, int y) {
this.x = x;
this.y = y;
}
}
static PrintWriter w = new PrintWriter(new OutputStreamWriter(System.out));
static Input f = new Input(System.in);
static class Input {
public BufferedReader reader;
public StringTokenizer tokenizer;
public Input(InputStream stream) {
reader = new BufferedReader(new InputStreamReader(stream), 32768);
tokenizer = null;
}
public String next() throws IOException {
while (tokenizer == null || !tokenizer.hasMoreTokens()) {
tokenizer = new StringTokenizer(reader.readLine());
}
return tokenizer.nextToken();
}
public String nextLine() throws IOException {
String str = null;
str = reader.readLine();
return str;
}
public int nextInt() throws IOException {
return Integer.parseInt(next());
}
public long nextLong() throws IOException {
return Long.parseLong(next());
}
public Double nextDouble() throws IOException {
return Double.parseDouble(next());
}
}
}
C. Everything Nim:
题目大意:
思路解析:
这道题最关键的点就是千万别都错题,我赛时就读错题了哈哈。
他是对于这剩下的n堆石子,你选择的k应当小于等于最小的堆的大小,然后当前所有堆减小k(这里特别关键,我就是赛时没有看到这个信息)。那么如果只要这个石堆中有1这样的石堆,那么他就只能选择1.
那么只要当前最小的石堆为1,那么可以发现你选择一后,其实是让后者赢,除非当前石堆都为1.
例如 1 3 5 6 -- 》 2 4 5 (a) -->1 3 4(b) --> 2 3(a) --> 1 2(b)--> 1(a) -- > win, 可以发现形如 x y z......x>=2的时候,谁先手谁就赢。 先手 可以选择x-1,那么整体变为 1 y-x+1 z-x+1,那么两次处理之后一定会删除一个数字,当只剩下一个石堆时,alice可以直接处理掉。
但是如果x=1,他此时只能选择1,没法使用策略来让自己获胜。
代码实现:
import java.util.*;
import java.io.*;
public class Main {
static int t;
public static void main(String[] args) throws IOException {
t = f.nextInt();
while (t > 0) {
solve();
t--;
}
w.flush();
w.close();
}
static int mod = 998244353;
static int inf = (int) 1e9;
public static void solve() throws IOException {
int n = f.nextInt();
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = f.nextInt();
}
Arrays.sort(a);
int ned = 1;
int k = 0;
int mx = a[n-1];
for (int i = 0; i < n; i++) {
if (a[i] < ned) continue;
if (a[i] == ned) {
ned = a[i] + 1;
k ^= 1;
if (a[i] == mx) k ^= 1;
}
}
if (k == 0) w.println("Alice");
else w.println("Bob");
}
public static void swap(int[] a, int i, int j) {
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
public static long qkm(long a, long b, long mod) {
long res = 1;
while (b > 0) {
if ((b & 1) == 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
public static class Pair {
int x, y, val;
public Pair(int ne, int val, int x) {
this.x = ne;
this.y = val;
this.val = x;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Pair pair = (Pair) o;
return x == pair.x && y == pair.y;
}
@Override
public int hashCode() {
return Objects.hash(x, y);
}
}
public static class Node {
int x, y;
public Node(int x, int y) {
this.x = x;
this.y = y;
}
}
static PrintWriter w = new PrintWriter(new OutputStreamWriter(System.out));
static Input f = new Input(System.in);
static class Input {
public BufferedReader reader;
public StringTokenizer tokenizer;
public Input(InputStream stream) {
reader = new BufferedReader(new InputStreamReader(stream), 32768);
tokenizer = null;
}
public String next() throws IOException {
while (tokenizer == null || !tokenizer.hasMoreTokens()) {
tokenizer = new StringTokenizer(reader.readLine());
}
return tokenizer.nextToken();
}
public String nextLine() throws IOException {
String str = null;
str = reader.readLine();
return str;
}
public int nextInt() throws IOException {
return Integer.parseInt(next());
}
public long nextLong() throws IOException {
return Long.parseLong(next());
}
public Double nextDouble() throws IOException {
return Double.parseDouble(next());
}
}
}
D. Missing Subarray Sum:
题目大意:
思路解析:
给你一个n和k然后利用最多25个数字组成一个序列,保证这个序列的所有子序列和包含(1-n除了k),看到只能使用25个值,很容易想到二进制,那么我们先利用二进制解决(1 - k-1)
那么我们再加入k+1,就可以解决 (1-2k) 再加入 2k 就可以解决 (1-4k) 但其实 (1-2k)中缺少了k,我们并不能解决3*k,所以我们再加入k+1,那么我们真正实现了(1-4k)再加入4k,可以发现此时也真正实现了(1-8k),那么一直往后递归就实现了。 // (注意k==1时应当加入 3)
代码实现:
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
int t = f.nextInt();
while (t > 0) {
solve();
t--;
}
w.flush();
w.close();
}
static int mod = 998244353;
static int inf = (int) 1e9;
public static void solve() throws IOException {
int n = f.nextInt(); int m = f.nextInt();
int[] a = new int[26];
int cnt = 0;
int res = 0;
for (int i = 0; i <= 20; i++) {
if (res + (1 << i) <= m - 1){
a[++cnt] = (1 << i);
res += (1 << i);
}else {
if ((m - 1) - res > 0){
a[++cnt] = (m - 1) - res;
res += (m - 1) - res - 1;
}
break;
}
}
res = m * 2;
a[++cnt] = m + 1;
a[++cnt] = m + 1;
a[++cnt] = m * 2+ 1;
while (res < n){
a[++cnt] = res;
res *= 2;
}
w.println(cnt);
for (int i = 1; i <= cnt; i++) {
w.print(a[i] + " ");
}
w.println();
}
public static void swap(int[] a, int i, int j) {
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
public static long qkm(long a, long b, long mod) {
long res = 1;
while (b > 0) {
if ((b & 1) == 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
public static class Pair {
int x, y, val;
public Pair(int ne, int val, int x) {
this.x = ne;
this.y = val;
this.val = x;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Pair pair = (Pair) o;
return x == pair.x && y == pair.y;
}
@Override
public int hashCode() {
return Objects.hash(x, y);
}
}
public static class Node {
int x, y;
public Node(int x, int y) {
this.x = x;
this.y = y;
}
}
static PrintWriter w = new PrintWriter(new OutputStreamWriter(System.out));
static Input f = new Input(System.in);
static class Input {
public BufferedReader reader;
public StringTokenizer tokenizer;
public Input(InputStream stream) {
reader = new BufferedReader(new InputStreamReader(stream), 32768);
tokenizer = null;
}
public String next() throws IOException {
while (tokenizer == null || !tokenizer.hasMoreTokens()) {
tokenizer = new StringTokenizer(reader.readLine());
}
return tokenizer.nextToken();
}
public String nextLine() throws IOException {
String str = null;
str = reader.readLine();
return str;
}
public int nextInt() throws IOException {
return Integer.parseInt(next());
}
public long nextLong() throws IOException {
return Long.parseLong(next());
}
public Double nextDouble() throws IOException {
return Double.parseDouble(next());
}
}
}
E. Folding Strip:
题目大意:
思路解析:
通过折叠 一定会将 11111111 (x个1) 折叠为 1, 同理0也是这样的
那么我们再观察 折叠的 一般形式 x个1 + y个0 + c个1 + c个1 + y个0 + x个1 一定会通过折叠变为 x个1 + y个0 + c个1又可以根据第一个的发现,那么折叠一定会变为 101 同时这样变为了最短形式 (那么可以发现任意一个折叠块都应当可以看作一个1和0交替出现的串)
那么就可以通过模仿这样的折叠来得到最小串长度,即寻找最短的01交替串
并且还可以发现折叠并不会影响其他位置的折叠
代码实现:
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
int t = f.nextInt();
while (t > 0) {
solve();
t--;
}
w.flush();
w.close();
}
static int mod = 998244353;
static int inf = (int) 1e9;
public static void solve() throws IOException {
// 通过折叠 一定会将 11111111 (x个1) 折叠为 1, 同理y也是这样的
// 那么我们再观察 折叠的 一般形式 x个1 + y个0 + c个1 + c个1 + y个0 + x个1 一定会通过折叠变为 x个1 + y个0 + c个1
// 又可以根据第一个的发现,那么折叠一定会变为 101 同时这样变为了最短形式 (那么可以发现任意一个折叠块都应当可以看作一个1和0交替出现的串)
// 那么就可以通过模仿这样的折叠来得到最小串长度
// 并且还可以发现折叠并不会影响其他位置的折叠
int n = f.nextInt();
char[] s = f.next().toCharArray();
int mx = 0; int mn = 0; int cur = 0;
for (int i = 0; i < n; i++) {
if ((cur % 2 == 0) == (s[i] == '1'))
cur++;
else cur--;
mx = Math.max(cur, mx);
mn = Math.min(cur, mn);
}
//w.println(cur);
w.println(mx - mn);
}
public static void swap(int[] a, int i, int j) {
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
public static long qkm(long a, long b, long mod) {
long res = 1;
while (b > 0) {
if ((b & 1) == 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
public static class Pair {
int x, y, val;
public Pair(int ne, int val, int x) {
this.x = ne;
this.y = val;
this.val = x;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Pair pair = (Pair) o;
return x == pair.x && y == pair.y;
}
@Override
public int hashCode() {
return Objects.hash(x, y);
}
}
public static class Node {
int x, y;
public Node(int x, int y) {
this.x = x;
this.y = y;
}
}
static PrintWriter w = new PrintWriter(new OutputStreamWriter(System.out));
static Input f = new Input(System.in);
static class Input {
public BufferedReader reader;
public StringTokenizer tokenizer;
public Input(InputStream stream) {
reader = new BufferedReader(new InputStreamReader(stream), 32768);
tokenizer = null;
}
public String next() throws IOException {
while (tokenizer == null || !tokenizer.hasMoreTokens()) {
tokenizer = new StringTokenizer(reader.readLine());
}
return tokenizer.nextToken();
}
public String nextLine() throws IOException {
String str = null;
str = reader.readLine();
return str;
}
public int nextInt() throws IOException {
return Integer.parseInt(next());
}
public long nextLong() throws IOException {
return Long.parseLong(next());
}
public Double nextDouble() throws IOException {
return Double.parseDouble(next());
}
}
}
F. Missing Subarray Sum:
题目实现:
思路解析:
经过分析发现,居中的子数组一定是一个,其他的数组是两个,那么应当有 (n+1)/2个居中数组,并且利用居中数组可以很方便的还原原数组。
那么假设我们丢失了一个居中的数组:我们只能用剩下的居中数组构造一个类似原数组的数组。
假设原数组为 1 2 3 2 1, 居中数组为 3 7 9,现在丢失7,那么我们可以利用剩下的居中数组,构造一个类似还原的数组为 3 3 3,我们可以发现只要丢失一个居中数组,那么我们在还原时,将某两个相邻数字合并 (丢失最大的时会把最后一个舍去 即 2 3 2)
那么假设现在数组为 a b c d c b a, 假设我们丢失最大的居中数组 我们可以利用 b c d c b,这个数组找到最大的子数组和为 (a+b+c+d+c+b) 利用这个和 (b+c+d+c+b)就可以得到想要的答案了,
假设我们丢失某个居中数组,得到还原数组 为 a (b+c) d (c+b) a, 除去在以得到的子数组和中除去还原的数组的子数组和的最大值 (a+c+d+c+b) * 2- (a+b+c+d+c+b+a) 来得到缺失的居中子数组和
假设我们缺失的为非居中子数组,那么我们就会让某个偶数的子数组和,变为奇数,此时就会让居中子数组变多, 策略就变为找到 这个还原数组的子数组和减去已有的子数组和 中最大的那个设为x,答案就是 x*2 - y,y是数组的整体和。
代码实现:
#include <bits/stdc++.h>
#include <unistd.h>
using namespace std;
using i64 = long long;
#define all(a) begin(a),end(a)
vector<i64> getArr(vector<i64> d, bool st){
deque<i64> q = {d[0]};
if (not st) q = {d[0] / 2, d[0]/2};
for(int i = 1; i < d.size(); i++){
q.push_front((d[i] - d[i-1])/2);
q.push_back((d[i]-d[i-1])/2);
}
return vector(all(q));
}
void solve(){
int n;
cin >> n;
vector<i64> a(n*(n+1)/2-1);
for(int i = 0; i < n*(n+1)/2-1; ++i){
cin >> a[i];
a[i] *= 2;
}
sort(all(a));
vector<i64> e;
for (auto x : a){
if (e.size() && e.back() == x) e.pop_back();
else e.push_back(x);
}
vector<i64> b = getArr(e, n & 1);
vector<i64> B {0};
vector<i64> a2;
i64 s = 0;
for(auto x : b) B.push_back(s+=x);
for(int i = 0; i < B.size(); ++i){
for(int j = i+1; j < B.size(); ++j){
a2.push_back(B[j] - B[i]);
}
}
sort(all(a2));
if(a2.size() > a.size()) swap(a,a2);
int i = 0;
for(; a.rbegin()[i] == a2.rbegin()[i] ; ++i);
i64 x = 2 * a.rbegin()[i] - s;
if(e.size() > (n+1) / 2) e.erase(find(all(e),x));
else e.insert(lower_bound(all(e),x),x);
vector<i64> ans = getArr(e, n&1);
for(auto x : ans){
cout << x/2 << " ";
}
cout << "\n";
}
int main()
{
cin.tie(0) -> sync_with_stdio(0);
cout.tie(0);
int t;
cin >> t;
while (t){
solve();
t--;
}
return 0;
}