题目1:游游画U
题目描述
游游想让你画一个大小为 n 的 "U" ,你能帮帮她吗?
具体的画法见样例说明。
输入描述:
一个正整数 .
1 ≤ n ≤ 50
输出描述:
共输出 4n行,每行输出一个长度为 4n 的,仅包含 '*' 和 '.' 两种字符的字符串。
样例1:
输入:
1
输出:
*..* *..* *..* .**.
样例2 :
输入:
2
输出:
**....** **....** **....** **....** **....** **....** .**..**. ..****..
个人题解:
过于简单,就不浪费大家时间了,模拟一下就可以了......
Python代码(AC):
n = int(input())
for i in range(n * 4 - n):
res = "*" * n + "." * (4 * n - 2 * n) + "*" * n
print(res)
for i in range(1,n + 1):
res = "." * i + "*" * n + "." * (n * 2 - i - n)
res2 = res[::-1]
print(res + res2)
题目2:游游的数组染色
题目描述
游游拿到了一个数组,其中一些数被染成红色,一些数被染成蓝色。
游游想知道,取两个不同颜色的数,且它们的数值相等,有多少种不同的取法?
我们定义,两种取法如果取的某个数在原数组的位置不同,则定义为不同的取法。
输入描述:
第一行输入一个正整数 ,代表数组的长度。
第二行输入个正整数 ,代表数组中的元素。
第三行输入一个长度为 ,仅包含 'R' 和 'B' 两种字符的字符串,第 个字符为 'R' 代表数组第个元素被染成红色,为 'B' 代表被染成蓝色。
1 ≤ n ≤ 200000
1 ≤ ≤
输出描述:
输出一个整数,代表取数的方案数量。
样例1:
输入:
5 1 2 1 2 2 BRRBB
输出:
3
说明1:
第一种取法,取第一个数和第三个数,颜色不同且都是1。
第二种取法,取第二个数和第四个数,颜色不同且都是2。
第三种取法,取第二个数和第五个数,颜色不同且都是2。
样例2 :
输入:
3 2 3 3 BBB
输出:
0
说明2:
所有数都是蓝色,显然取不出两个颜色不同的数。
个人题解:
题目简述:给一个数值数组arr,一个字符串数组strings,现要在字符串数组strings中找两个不同的字符同时保证在arr数组中对应索引处的数值是不同的,问有多少种这样的取法?
个人猜测考察点:maybe...哈希吧,我也不知道考察什么hhh,瞎写就是了....
个人题解(较笨):两个字典(哈希),分别记录B、R两个不同颜色的数出现的个数。从字符串中从左往右依次寻找B/R颜色,再将其对应索引的arr中的数值分别存储到各自的字典中。
答案:
由于B/R两种不同颜色字符的索引和arr中数值元素的索引相对应,因此diff1和diff0两个字典已经分别存储了各颜色对应的数值的出现次数,字典中的键是arr中的数值,值是出现次数;那么本题的答案就是两个不同字典(不同颜色)的相同数值(数值相等)的值的积的和。(注意这个数值一定是要在两个字典中同时存在才可以,其他情况continue就可以了)
Python代码(AC):
import sys
input = sys.stdin.readline
def main():
n = int(input())
arr = list(map(int,input().split()))
string = input()
# 处理1 0
diff1 = dict()
diff0 = dict()
for i in range(n):
if string[i] == "B":
diff1[arr[i]] = diff1.get(arr[i],0) + 1
if string[i] == "R":
diff0[arr[i]] = diff0.get(arr[i],0) + 1
# 计算
res = 0
for d in diff1:
if d not in diff0: continue
tmp = diff1[d] * diff0[d]
res += tmp
print(res)
main()
题目3:游游的交换字符
题目描述
游游拿到了一个01串(仅由字符'0'和字符'1'构成的字符串)。游游每次操作可以交换两个相邻的字符,例如,对于字符串"11001"而言,游游可以交换第二个字符和第三个字符变成"10101"。
游游希望最终字符串任意两个相邻的字符都不相同,她想知道最少需要多少操作次数?保证答案是有解的,即最终一定能形成任意两个相邻的字符都不相同的字符串。
输入描述:
一行仅由 '0' 、 '1' 组成的字符串,字符串长度 满足 2 ≤ ≤ 200000。
输出描述:
游游使得相邻两个字母不等的最少操作次数。
样例1:
输入:
11100
输出:
3
说明1: 先交换第三个、第四个字符,得到字符串"11010"。然后交换第二个、第三个字符,得到字符串"10110"。最后交换第四个、第五个字符,得到字符串"10101"。总共交换3次。
样例2 :
输入:
01011
输出:
2
说明2: 先交换前两个字符,得到字符串"10011",然后交换第三个、第四个字符,得到字符串"10101"。
个人题解:
题目简述:给一个01串,可以有x次操作,每一次操作可以交换两个相邻的字符,现希望x次操作完成之后字符串的任意两个相邻的字符都不相同,求最少的操作次数x。
个人猜测考察点:贪心(瞎写)。。在每一步选择最优的操作,通过局部最优解得到全局最优解。
个人题解(不一定最优):定义个solve函数,记录某个字符string放到arr数组(理想位置 并非真的储存)中的最少操作次数,返回值即为最少操作次数ans和字符string在arr中的出现次数。我们的目标是尽可能地让string在arr中(理想)隔空铺满,即计算arr中的真实值string的索引位置与理想位置的索引的差值的绝对值之和ans。
我们举个例子来说明一下函数的计算方法:假设当前输入字符串
arr
是 "11001",我们希望将字符'0'放入列表arr1(理想,没有真实存在),理想的列表arr1应该是 "01010"。现在,我们来计算将字符 0 放入列表arr1的最少操作次数ans
。① 找到字符 0 在输入字符串
arr
中的位置,字符 0 在索引 2 和 3 处;② 计算字符 0 在理想位置的索引
i,
理想位置的索引是 0 和 2;③ 计算字符 0 在输入字符串
arr
中出现的位置与理想位置的索引之间的距离:a. 第一个字符 0:索引差为 2 - 0 = 2;
b. 第二个字符 0:索引差为 3 - 2 = 1;
④ 将字符 0 在输入字符串中的距离之和累加:
ans = 2 + 1 = 3。
因此对于输入字符串 "11001",将字符 0 放入列表a的最少操作次数是 3 次。
答案:
如果字符串arr的长度为偶数的话,说明在字符串中,无论字符 0 和 1 的出现次数如何,我们总是可以通过一定的操作将相邻的字符变成不相同的字符;
但是如果字符串arr长度为奇数的话,那么字符串arr中的字符 1 和字符 0 必有一者的个数大于另一者,在这种情况下,我们就无法通过贪心放置字符 0 和字符 1,然后取min来满足题意要求。(这其实是我wa了好久的原因 em....好菜)解决办法就是单独拿出来处理。然后就过了。。。
Python代码(AC):
import sys
input = sys.stdin.readline
# 将某个字符string放到arr的最少操作次数 -》 计算与预期位置的索引的差值的绝对值之和
def solve(arr,string):
ans = 0
lens = 0 # string 在 arr 中出现的次数
tmp_ind = 0
for ind,val in enumerate(arr):
if val == string:
ans += abs(ind - tmp_ind)
tmp_ind += 2 # 理想的位置
lens += 1 # 目标字符计数
return ans,lens
def main():
arr = input().strip()
n = len(arr) # 字符串长度
ans0, len0 = solve(arr, "0")
ans1, len1 = solve(arr, "1")
if n % 2 == 0:
print(min(ans0, ans1))
else:
# 奇数长度的话 - 单独处理
print(ans1 if len1 > len0 else ans0)
main()
题目4:游游的9的倍数
题目描述
游游拿到了一个数字串,她想取一个该数字串的子序列(子序列在原串中可以不连续),使得该子序列是9的倍数。子序列可以包含前导零。
游游想知道,一共能取多少个合法的子序列?答案请对 + 7 取模。
我们定义,若两个子序列在原串中的位置不同,则认为它们不同。
输入描述:
一个长度不超过200000的,仅由'0'~'9' 十种字符组成的字符串。
输出描述:
子序列是9的倍数的数量。答案请对 + 7 取模。
样例1:
输入:
1188
输出:
5
说明1: 共可以取4个不同的"18"子序列,和一个"1188"子序列,都是9的倍数。
样例2 :
输入:
0123
输出:
1
说明2: 只有子序列"0"是9的倍数。
个人题解:
题目简述:给一个数字字符串,需要我们找出所有的子序列(含不连续子序列),使得该子序列的数值是9的倍数。求这样的子序列的个数,然后对答案取余即可。
个人猜测考察点:状压DP。。。
个人题解(不一定最优):DP是一个很复杂的知识点,具体步骤如下:(maybe笔者太笨啦hhh推理的有点慢,如有优解,请在评论区共同分享探讨,不胜感激!!)
分三个步骤:
1. 定义状态:dp[i][j]表示以前个字符为结尾的子序列中,模9后余的子序列的个数。
2. 初始状态:对于长度为i的子串arr[i],有dp[i][arr[i] % 9] = 1,其余dp[i][j]均为0。
3. 状态转移:对于当前每个新的字符arr[i],有两种选择:要么将其选为新的结尾字符,要么就不选。若将其作为新的结尾字符的话,新的模9后余数应该为(j + arr[i])%9, 那么转移到当前状态的式子应该是:
dp[i][j] = dp[i-1][(j - arr[i])%9]
若不将其作为新的结尾字符的话,那么当前状态跟上一个状态的子序列个数一致,即转移到当前状态的式子应该是:
dp[i][j] = dp[i-1][j]
综上,状态转移方程可以表示为:
dp[i][j] += dp[i-1][(j - arr[i]) % 9] + dp[i-1][j]
4. 答案:最终的答案为dp[n-1][0],其中n为数字字符串的长度。
Python代码(AC):
import sys
input = sys.stdin.readline
def solve(arr,Mod = pow(10,9) + 7):
n = len(arr)
# dp[i][j]表示以数字串的前i个字符为结尾的子序列中,模9后余j的子序列的个数 =》 dp[i][j] 表示的是满足条件的子序列的个数
dp = [[0 for i in range(9)] for j in range(n)]
for i in range(n):
# 初始状态: 前i个字符结尾的子序列中,模9后余数为j的个数是1个
dp[i][arr[i] % 9] = 1
for j in range(9):
# 将s[i]作为新的结尾字符 当前状态新的模9的余数应该为(j + s[i]) % 9
dp[i][j] %= Mod
dp[i][j] = (dp[i][j] + dp[i - 1][j] + dp[i - 1][(j - arr[i]) % 9]) % Mod
return dp[n - 1][0]
def main():
arr = list(map(int,input().strip()))
res = solve(arr)
print(res)
main()