Python解题 - CSDN周赛第43期

感觉周赛越来越无趣了,基本都是考过的题目。上期周赛也是,4道题都曾考过,问哥也都写过题解,奖品也不吸引人,实在没什么好写了。

回想前段时间用力过猛,刷了C站大部分OJ题,以致于现在看到题目就直接套答案了。甚至于误打误撞,发现了周赛的测试链接,上了一次处罚名单。。。嗯(无辜脸)。。。

本期还是全部考过,除了第二题没写过题解,这里就把它补上吧。


第一题:判断胜负

已知两个字符串A,B。连续进行读入n次。每次读入的字符串都为A|B。输出读入次数最多的字符串。

分析

17期考过,可以参考问哥之前的题解。不过其实也没啥好解的,就是比较两个字符串哪个出现次数最多,平局就输出“dogfall”——顺便学个英文单词。


第二题:小豚鼠搬家

小豚鼠排排坐。 小艺酱买了一排排格子的小房子n*m,她想让k只小豚鼠每只小豚鼠都有自己的房子。 但是为了不浪费空间,她想要小房子的最外圈尽量每行每列都有一只小豚鼠居住(小豚鼠也可以住在中间的格子,只需保证房子最外围的行和列至少住一只豚鼠即可,无需每行每列都有豚鼠)。 小艺酱想知道自己有多少种方案安排小豚鼠。

输入描述:输入整数n,m,k。(1<=n,m<=20,0<=k<=n*m)

输出描述:输出方案数,答案对1e9+7取模。

示例:

输入3 3 2
输出2

分析

也曾在13期考过,但是网上靠谱的题解不多。

本题本质上就是排列组合,总共有 n*m 个格子,要放进去 k 只小豚鼠,如果不加任何限制的话,学过数学的都知道,总共有 C_{n*m}^{k}=\frac{(n*m)!}{k!*(n*m-k)!} 种方案。但是题目要求最外面一圈的每行每列(实际上就是顶底两行与左右边两列)至少各有一只小豚鼠。在检查这个条件时,小豚鼠的数量可以重复计入。比如给的例子中,只有两只小豚鼠,于是只能这样放才能满足要求(也就是两种方案):

明白了题目的要求,我们可以先思考一下最朴素的穷举做法:先找出所有 C_{n*m}^{k} 种可能,然后逐一检查每种可能里,上、下、左、右四条边里有没有豚鼠。

这很容易,只要使用 python 内置的 combinations 函数,找出所有从坐标 (0,0) 到 (n-1,m-1) 的所有坐标中取出 k 个的组合,然后逐一检查其中是否存在横坐标为 0 和 n-1,以及纵坐标为 0 和 m-1 的坐标。

这种方法可以保证找到答案,但绝对会超时。因为我们其实并不关心每种方案的具体坐标有哪些,而只需要知道方案的数量。于是,我们拿总的方案数,减去不符合要求的方案不就可以了?

我们已知总的方案数是 C_{n*m}^{k},那么不符合要求的有哪些方案呢?

  1. 一条边没有豚鼠:
    1. 顶边或底边没有豚鼠:2*C_{(n-1)*m}^{k}
    2. 左边或右边没有豚鼠:2*C_{n*(m-1)}^{k} 
  2. 两条边没有豚鼠:
    1. 顶边和底边没有豚鼠:C_{(n-2)*m}^{k}
    2. 左边和右边没有豚鼠:C_{n*(m-2)}^{k}
    3. 顶边和左边、顶边和右边、底边和左边、底边和右边没有豚鼠:4*C_{(n-1)*(m-1)}^{k}
  3. 三条边没有豚鼠:
    1. 顶边、左边、底边,或顶边、右边、底边没有豚鼠:2*C_{(n-2)*(m-1)}^{k}
    2. 左边、顶边、右边,或左边、底边、右边没有豚鼠:2*C_{(n-1)*(m-2)}^{k}
  4. 四条边没有豚鼠:C_{(n-2)*(m-2)}^{k} 

但是别急,当我们拿总数减去四次一条边没有豚鼠的情况的时候,实际上,我们重复减去了那些两条边、三条边的情况,所以我们要把两条边的情况加回来,但是这样一来,又重复加上了三条边的情况,所以还要将三条边的情况减去。。。所以,相信你也已经看出来了,实际上这题考察的又是容斥原理

如果我们用 S 代表总的方案的集合,A,B,C,D 各自代表上、下、左、右四条边上没有豚鼠的情况的集合,可以用数学公式表示如下:

ans = S-A-B-C-D+A\cap B+ A\cap C+ A\cap D+ B\cap C+ B\cap D+ C\cap D - A\cap B\cap C-A\cap B\cap D-A\cap C\cap D-B\cap C\cap D+A\cap B\cap C\cap D

一言以蔽之:将四种集合进行排列组合,如果组合中包含的集合个数是奇数,就减去,如果是偶数,就加上。

所以,回到我们这道题,结合我们刚才列出的所有情况,就可以得到答案如下:

ans = C_{n*m}^{k}-2*C_{(n-1)*m}^{k}-2*C_{n*(m-1)}^{k}+C_{(n-2)*m}^{k}+C_{n*(m-2)}^{k}+4*C_{(n-1)*(m-1)}^{k}-2*C_{(n-2)*(m-1)}^{k}-2*C_{(n-1)*(m-2)}^{k}+C_{(n-2)*(m-2)}^{k}

代码就省略了吧,无非是用代码计算这个公式罢了。 


第三题:醉酒的狱卒

某监狱有一个由n个牢房组成的大厅,每个牢房紧挨着。每个牢房里都有一个囚犯,每个牢房都是锁着的。一天晚上,狱卒感到无聊,决定玩一个游戏。在第一轮,他喝了一杯威士忌,然后跑下大厅,打开每个牢房的锁。在第二轮比赛中,他喝了一杯威士忌,然后跑下大厅,锁上每隔一个的牢房的锁(牢房2、4、6…)。在第三轮比赛中,他喝了一杯威士忌,然后跑下大厅。他每隔三个牢房(第3、6、9号牢房)就去一次。如果牢房被锁上了,他就把它打开;如果牢房门打开了,他就锁上牢房。他重复 n 轮,喝最后一杯,然后昏倒。一些囚犯(可能为零号)意识到他们的牢房被解锁且狱卒丧失了行动能力。他们就可以立即逃跑。现在根据牢房数量,确定有多少囚犯越狱。

分析 

19期考过,题干很复杂,实际很简单。本题存在 O(1) 的解法,可以参考问哥之前的题解


第四题:会议安排

开会了!作为一个集体,开会的时候桌子当然是需要和老大相邻的!(老大可能坐在桌子上边) 小艺被分配到排桌椅的活,可是小艺的力气都用在吃上了,怎么可能搬动这些桌椅呢。 她决定用现有的布局当作是会议座位安排。每个桌子分配一个人。互相连接相同字符表示一个桌子,如UVV表示2张桌子,UVU则表示3张桌子。小艺想知道选择某个桌子之后老大身边能围多少人?

分析

20期考过,可以参考问哥之前写的题解

关于字符串的处理,问哥一直觉得很麻烦,所以如果有更好的做法,还请告诉我,谢谢。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

请叫我问哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值