[acwing周赛复盘] 第 63 场周赛20220806

一、本周周赛总结

  • T3调试用的break没删wa了一次,搞笑了。在这里插入图片描述

在这里插入图片描述

二、 4503. 数对数量

链接: 4503. 数对数量

1. 题目描述

在这里插入图片描述

2. 思路分析

签到题,枚举x,y=n-x,检查y是否在范围内即可。

3. 代码实现

import collections
import io
import os
import sys
from collections import deque

if sys.hexversion == 50923504:
    sys.stdin = open('input.txt')
else:
    input = sys.stdin.readline
MOD = 10 ** 9 + 7


def solve(a,b,n):
    ans = 0
    for x in range(0,a+1):
        y = n-x
        if 0<=y<=b:
            ans += 1


    print(ans)


if __name__ == '__main__':
    if False:
        n = int(input())
        m, n = map(int, input().split())
        s = list(map(int, input().split()))
    a = int(input())
    b = int(input())
    n = int(input())
    solve(a,b,n)

三、4504. 字符串消除

链接: 4504. 字符串消除

1. 题目描述

在这里插入图片描述

2. 思路分析

  • 没想出来什么制胜策略。
  • 因为每次都得消除1对且只能消除一对,那么直接检查能消除多少对即可。
  • 由于消除中间的,两边可能匹配上,用栈来消除。
  • 最后检查消除了多少次,奇数次则获胜。

3. 代码实现

import collections
import io
import os
import sys
from collections import deque

if sys.hexversion == 50923504:
    sys.stdin = open('input.txt')
else:
    input = sys.stdin.readline
MOD = 10 ** 9 + 7


def solve(s):
    stack = []
    cnt = 0
    for c in s:
        if stack  and stack[-1] == c:
            cnt += 1
            stack.pop()
        else:
            stack.append(c)

    if cnt & 1:
        print('Yes')
    else:
        print('No')




if __name__ == '__main__':
    if False:
        n = int(input())
        m, n = map(int, input().split())
        s = list(map(int, input().split()))
    s = input()
    solve(s)

四、4505. 最大子集

链接: 4505. 最大子集

1. 题目描述

在这里插入图片描述

2. 思路分析

比赛时写的是错的暴力枚举。以下是正确的。
  • 这题有个结论,答案数组长度最多是3,且是等差数列,公差d是2的幂次。
  • 证明3的情况,即若d1、d2、d1+d2都是2的幂次,当且仅当d1=d2:
  • 排好序后假设数组是[a,b,c],差是d1,d2。且d1,d2都是2的幂次。
  • 那么什么情况下d1+d2也是2的幂次呢。
  • 从2进制考虑,d1和d2分别是只有一个1的二进制数,当且仅当他们相等的情况下,求和仅有一个1,且进位。
  • 证明完3,第4个数无论如何都插入不进来了,它和第一个数的差是3倍公差,不是2的幂

以下是错误的原题解:

忘记删除调试用的break,wa了一次,蛋疼。

  • 模拟了半天,没想出什么好办法,只能暴力。
  • 但是暴力的时候可以倍增枚举:
  • 对每个数j,检查比它大1的数是否在数组里;检查比它大2的数;比它大4的数;比它大8的数。。。
  • 这个数b如果在数组里,还得检查b是否和当前答案集里的每个数差都是2的幂。
  • 这里先得写一个judge,位运算用O(1)时间检查这个数是不是2的幂。
  • 那么对每个数,他最多有log(2e9)的数在集合里,只需要枚举这么多大概是30。
  • 检查也是log(2e9),因此总复杂度是O(n* lgT lgT)=O(n30*30)
    这个代码会被以下case hack;答案是3\n 0 8 16
4
0 2 8 16

3. 代码实现

# Problem: D. Points and Powers of Two
# Contest: Codeforces - Codeforces Round 486 (Div. 3)
# URL: https://codeforces.com/contest/988/problem/D
# Memory Limit: 256 MB
# Time Limit: 4000 ms

import sys

RI = lambda: map(int, sys.stdin.buffer.readline().split())
RS = lambda: map(bytes.decode, sys.stdin.buffer.readline().strip().split())
RILST = lambda: list(RI())
DEBUG = lambda *x: sys.stderr.write(f'{str(x)}\n')

MOD = 10 ** 9 + 7
PROBLEM = """https://codeforces.com/contest/988/problem/D

输入 n(≤1e5) 和长为 n 的整数数组 a(-1e9≤a[i]≤1e9),没有相同元素。

从 a 中选择尽量多的数,组成集合 b,要求 b 中任意两个数的差的绝对值都是 2 的幂次。
输出 b 的大小以及 b 中的每个数。(没有顺序要求,多解输出任意一解)
输入
6
3 5 4 7 10 12
输出 
3
7 3 5

输入
5
-1 2 5 8 11
输出 
1
8
"""
"""结论题 数学+倍增枚举
acw63场T3
这题有个结论,答案数组长度最多是3,且是等差数列,公差d是2的幂次。
证明3的情况,即若d1、d2、d1+d2都是2的幂次,当且仅当d1=d2:
    排好序后假设数组是[a,b,c],差是d1,d2。且d1,d2都是2的幂次。
    那么什么情况下d1+d2也是2的幂次呢。
    从2进制考虑,d1和d2分别是只有一个1的二进制数,当且仅当他们相等的情况下,求和仅有一个1,且进位。
证明完3,第4个数无论如何都插入不进来了,它和第一个数的差是3倍公差,不是2的幂。
"""
"""https://codeforces.com/contest/988/submission/171194913

如果选两个数 x<y,那么枚举 k 寻找 y-x=2^k,做法类似两数之和。

如果选三个数 x<y<z,那么必须有 y-x=z-y=2^k,否则 z-x 不是 2 的幂次。做法同 2367. 算术三元组的数目

选四个是无法做到的,根据上面可知必须是等差数列,但这样最大-最小是 3*2^k,也不是 2 的幂次。
那么选大于四个数就更不可能了,因为相当于在四个数的基础上多了一个数,四个数不行就更别说大于四个数了。"""



#   358    ms
def solve():
    n, = RI()
    a = set(RILST())
    mx = max(a)
    ans = [mx]
    for x in a:
        for k in range(33):
            t = x + (1 << k)
            if t > mx:
                break
            if t in a:
                ans = [x, t]
                if (x + (1 << (k + 1))) in a:
                    print(3)
                    return print(*ans, x + (1 << (k + 1)))

    print(len(ans))
    print(*ans)


if __name__ == '__main__':
    solve()

六、参考链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值