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

点此看题面

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

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

考虑这道题中总方案数是非常显然的,就是\(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)

败得义无反顾,弱得一无是处