A Packets
大概内容就是你有n个硬币,要求将这n个硬币分成x份,使得给出任意k, 1 <= k <=n, 可以从x份硬币中拿出任意份,组成k。求最小的x。
考虑对于任意整数n,都可以表示为一个二进制数字。这就是最简单的分割方法了,分配出来就是
1,2,4,8,16 。。。。2^(x-1),n-2^(x-1)
n = int(input())
def find(x, count):
if(x > (1 << count)):
return find(x - (1 << count) , count + 1)
else:
return count + 1
print(find(n, 0))
B Reach Median
大意就是,给定n和k,允许修改任意的数字,是的k变成n个数字里面的中位数。
简单贪心算法即可解决,先将n个数字排序,然后检查中位数。如果当前中位数小于n,则从中间那个数字加到n,然后向后,一直加,直到遇到一个大于等于n的数字即可。如果大于n,则减至n,然后向前减,直到遇到一个小于等于n的数字。
[n,s] = map(int, input().split())
input_list = list(map(int, input().split()))
middle = int(n /2 )
input_list = sorted(input_list)
if input_list[middle] == s:
## no need
print(0)
elif input_list[middle] > s:
cur = middle
ret = 0
while cur >= 0 and input_list[cur] > s:
ret = ret + input_list[cur] - s
cur = cur - 1
print(ret)
elif input_list[middle] < s:
cur = middle
ret = 0
while cur < n and input_list[cur] < s :
ret = ret + (s - input_list[cur])
cur = cur + 1
print(ret)
C Equalize
通过翻转01或者交换bit使得两个二进制字符串等价。翻转一次01消耗1,交换两个bit消耗|x-y|。很明显,除非两个bit交换的时候为相邻的bit,否则翻转两次的消耗都比交换小。逻辑是挺简单的,但是因为输入比较大,所以用python3很容易就TLE了。。。被测试用例TLE了好几次,放弃了,用cpp把。。。需要注意的是,只有当相邻的两个bit是不一样的,并且两个bit都跟目标不同,才应该交换,否则还是应该翻转。
#include<bits/stdc++.h>
int main(int argc, char *argv[])
{
int n = 0;
int ret = 0;
std::string a,b;
std::cin >> n;
std::cin >> a;
std::cin >> b;
for(int i = 0 ; i < n ;i ++)
{
if(a[i] == b[i])
{
continue;
}
else if(i + 1 < n && a[i+1] != b[i+1] && a[i] != a[i+1])
{
ret++;
i++;
}
else{
ret++;
}
}
std::cout << ret << std::endl;
return 0;
}
D valid BFS
给定节点的连接方式,然后给出一个遍历顺序,要求检测遍历的顺序是否为bfs方式。这个题目我当时没有做出来,其实挺简单的。。。需要注意的问题就两个,
1,给定的节点是无向的。
2,搜索的时候不要求检查该节点下子节点遍历顺序,但是要求一定是按照入队顺序去遍历,先遍历到的,需要先入队列。
E Trip
同没有做出来,感觉好复杂。。。后来看了别人的做法,来bb一下。题目大意是,每天有两个人成为朋友,每天,你都需要安排出行,出行要求对于任意一个人,要么他不参加,如果他参加,他必须有k个以上的朋友也参加。求每天参加活动的最多人数。
按照顺序处理这个结果,不好整,但是反过来就比较好整了。先把所有好友关系读进来。然后把所有人都拉到出行群。ok,大家都进来了,开始迭代删除朋友不够的人,从最后一天开始,一个个抹掉好友关系。处理完之后,打印出来即可。