用Python做50道ACM之《洗牌问题》

30.洗牌问题

http://acm.fzu.edu.cn/problem.php?pid=1062

因为一副牌中每张牌具有唯一性,因此使用递增数字代替每张牌构建给定2n长度的列表,然后按题目规则进行列表变化记录直到第一次恢复原来严格递增顺序时候的次数即可。但是这个方法面对较大的n时计算复杂度非常大。

def times(n):
    li=[i for i in range(0,2*n)]
    origin=li.copy()
    ahead=li[:n] # 前半部分牌
    behind=li[n:] # 后半部分牌
    count=0
    while True:
        for i in range(0,n):
            li[2*i+1]=ahead[i]
            li[2*i]=behind[i]
        count+=1
        ahead=li[:n]
        behind=li[n:]
        if li==origin:
            return count

# 第二种方法,通过观察,当第一张牌出现在第n+1的位置时,其下一次将回到原位。
# 第一张牌每次洗牌后所处的位置规律为:
# 当第一张牌位于前n个位置的时候,其下一次所在位置为当前位置的2倍处
# 当第一章牌位于后n个位置的时候,其下一次所在位置为当前位置的(idx-n)*2-1
def times_quick(n):
    count=0
    i=1
    while i!=n+1:
        if i<=n:
            i*=2
        else:
            i=(i-n)*2-1
        count+=1
    return count+1

import sys

for read_in in sys.stdin:
    if read_in:
        print(times_quick(int(read_in.rstrip())))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值