【蓝桥杯训练】第四天1254
1254
小明有3颗红珊瑚,4颗白珊瑚,5颗黄玛瑙。
他想用它们串成一圈作为手链,送给女朋友。
现在小明想知道:如果考虑手链可以随意转动或翻转,一共有多少不同的组合样式?
输出
请你输出该整数。不要输出任何多余的内容或说明性的文字。
注意
手链是可以转动翻转
算法
数学方法
- 首先要清楚这是一种环排列,并且是立体排列
- 用最原始的做法简化思考,当成一行排列:
2.1 有12个珠子排列12!,但是跟相同珠子的相对位置没有关系,所以有12!/(5!4!3!)种 - 考虑环排列,环排列是因为相对位置无法确定,即需要一个参考。所以先拿一个占位,那么之前总数为 12!/(5!4!3!)/12 = 2310 种
- 考虑翻转:
4.1 翻转必定要选一个为轴,干好红色和黄色为奇数,必定要1红1黄为轴。
4.2 只看一边就是1红2白2黄的排列组合,如2.1一般 5!/(1!2!2!) = 30 种
4.3 献出开翻转一样的,其他组合必有一对重复的。(2310-30)/2 - 最终数量应该是 30 + (2310-30)/2 = 1170
有不足欢迎讨论。
暴力破解法
- 枚举暴力在当前这个数量还不算太大,12! = 479001600 = 4.7亿
- 转动即是123,231,312是一种,那利用字符串扩大一倍即可用寻找子串解决,即是123123中可以找到123,231,312
- 翻转将2的序列逆序即可321321
题解
说明:
- 利用了itertools.permutations产生全排列,他是一个生成器,每次返回的是一个元组,product可以产生笛卡尔积
- 利用了functools.reduce,将返回额元组合为字符串
#!/usr/bin/python3
import time
from itertools import permutations
from functools import reduce
def tupToString(tup):
return reduce(f, tup)
start = time.time()
f = lambda a, b: a + b
chars = 'aaabbbbccccc'
sum = 0
v = []#存将要寻找的
for i in permutations(chars):
SF = 0#找到了的标志量
chars = tupToString(i)
for com in v:
if chars in com:
SF = 1
break
if SF:
continue
chars2 = chars + chars#可以任意转动
v.append(chars2)
chars2 = chars2[::-1]#可以翻转
v.append(chars2)
sum += 1
# print(v)
print(sum)
end = time.time()
print('runtime:{}s'.format(end-start))
纯粹于当下,执着于理想。