【BZOJ2227】[ZJOI2011] 看电影(组合数学)

点此看题面

  • (n)个人和(k)个位置,轮到每个人时会随机给出一个数字(lin [1,k]),找到大于等于(l)的最小空位置坐下,如果没有则只能站着。
  • 求每个人都坐下的概率。
  • (n,kle200)

概率=合法方案数/总方案数

考虑这道题中总方案数是非常显然的,就是(k^n)

因此,问题的核心就在于,如何求出合法方案数,对于这个就需要几步很妙的转化。

我们不妨在最后添上一个位置(k+1),则第一个站着的人就可以坐到第(k+1)个位置上,因此没有人站着等价于第(k+1)个位置是空的。

然后我们还可以在第(k+1)个位置之后加上一个传送门,把这个东西连成一个圆,保证每个人都能找到位置坐,方便答案的计算。(当然一个合法方案中传送门是不会被用到的,因为要用传送门就说明第(k+1)个座位非空,因此这步转化不会影响合法方案数)

那么相当于每个人都可以在这(k+1)个位置中任选,根据之后每个人选的数与第一个的人选的数之差,一共有((k+1)^{n-1})种可能的选法。

而这些不同的选法有一个共通之处,就是空位置数量都是(k-n+1)

现在我们需要找一个位置作为第(k+1)个位置把环断开,只要满足选择的是这(k-n+1)个空位置中的某一个即可。

因此合法方案数就应该是((k+1)^{n-1}(k-n+1))

由于题目要求直接给出答案的既约分数,直接上Python就好了。

代码:(O(Tn))

def gcd(a,b):#最大公约数,用于约分
    return a if b==0 else gcd(b,a%b)
Tt=int(input())
for T in range(Tt):
    st=input().split()
    n=int(st[0])
    k=int(st[1])
    if(n>k):
        print("0 1")#如果n>k,显然无解
    else:
        a=((k+1)**(n-1))*(k-n+1)#合法方案数
        b=k**n#总方案数
        d=gcd(a,b)
        print(a//d,end=' ')
        print(b//d)

败得义无反顾,弱得一无是处
原文地址:https://www.cnblogs.com/chenxiaoran666/p/BZOJ2227.html