zoukankan      html  css  js  c++  java
  • 【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)
    
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    2.4 将类内联化
    2.3 提炼类
    2.2 搬移字段
    2.1 搬移函数
    1.8 替换你的算法
    1.7 以函数对象取代函数
    1.7 移除对参数的赋值动作
    1.6 分解临时变量
    1.5 引入解释性变量
    1.4 以查询取代临时变量
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/BZOJ2227.html
Copyright © 2011-2022 走看看