[ZJOI2011] 看电影(movie) (组合数+高精度)

题目描述

到了难得的假期,小白班上组织大家去看电影。但由于假期里看电影的人太多,很难做到让全班看上同一场电影,最后大家在一个偏僻的小胡同里找到了一家电影院。但这家电影院分配座位的方式很特殊,具体方式如下:

  1. 电影院的座位共有K个,并被标号为1…K,每个人买完票后会被随机指定一个座位,具体来说是从1…K中等可能的随机选取一个正整数,设其为L。
  2. 如果编号L的座位是空位,则这个座位就分配给此人,否则将L加一,继续前面的步骤。
  3. 如果在第二步中不存在编号L的座位,则该人只能站着看电影,即所谓的站票。

小白班上共有N人(包括小白自己),作为数学爱好者,小白想知道全班都能够有座位的概率是多少。

输入格式

输入文件第一行有且只有一个正整数T,表示测试数据的组数。
第2~T+1行,每行两个正整数N,K,用单个空格隔开,其含义同题目描述。

输出格式

输出文件共包含T行。
第i行应包含两个用空格隔开的整数A,B,表示输入文件中的第i组数据的答案为A/B。(注意,这里要求将答案化为既约分数)

样例
样例输入
    3
     1 1
     2 1
     2 2
样例输出
1 1
 0 1
 3 4
数据范围与提示

对于100%的数据 T<=50,N,K<=200

题解

可以在k+1的位置加一个座位再把它连成一个环,情况数便为(k+1)^n;

因为是个环所以去重为(k+1)^(n-1);

最后拆环并且首位不能有人,ans=(k+1)^(n-1)*(k-n+1);

最后的概率便是 p=ans/k^n;

 输出要用分数形式,直接上高精乘,我们观察式子发现上下最多有可能是(k-n+1)和k^n有公因子,所以跑gcd不断除出去。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll T,t,n,k,A,B,C,sum[3][10000],len[3];
ll gcd(ll x,ll y)
{
        return y==0?x:gcd(y,x%y);
}
void X(ll x,ll h)
{
        ll y=0;
        for(int i=0;i<=len[h];i++)
        {
                ll z=sum[h][i]*x+y;
                sum[h][i]=z%10;
                y=z/10;
        }
        while(y)
        {
                sum[h][++len[h]]=y%10;
                y/=10;
        }
}
void print(ll h)
{
        for(int i=len[h];i>=0;i--) printf("%lld",sum[h][i]);
}
void work()
{
        memset(len,0,sizeof(len));
        memset(sum,0,sizeof(sum));
        sum[1][0]=1;
        sum[2][0]=1;
        scanf("%lld%lld",&n,&k);
        if(n>k)
        {
                puts("0 1");
                return;
        }
        C=k-n+1;
        B=n;
        while(C!=1&&B>0)
        {
                ll o=gcd(C,k);
                B--;
                X(k/o,2);
                C/=o;
        }
        X(C,1);
        for(int i=1;i<=n-1;i++) X(k+1,1);
        for(int i=1;i<=B;i++) X(k,2);
        print(1);
        printf(" ");
        print(2);
        puts("");
}
int main()
{
        scanf("%lld",&T);
        while(T--) work();
        return 0;
}
View Code

 

 

转载于:https://www.cnblogs.com/AthosD/articles/11138206.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值