[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。(注意,这里要求将答案化为既约分数)

输入输出样例

输入样例#1:
3
1 1
2 1
2 2
输出样例#1:
1 1
0 1
3 4
范围
0<=n,k<=200
题解
组合数学加高精度
首先这是一个古典概型,概率等于合法的方案数除以总方案数。总方案数=K^N
合法方案数的计算:在最后面加一个座位,然后所有的座位连成一个环。现在那么总方案数等于(K+1)N
每种环都算了(K+1)次,所以除以(K+1),最后抽调一个空白的座位来构造一个合法的方案,所以要乘(NK+1)
ans=(K+1)^(N-1)*(K-N+1)/K^N

高精度用十位一进
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 using namespace std;
  6 long long w=1e9;
  7 long long c[20001],s1[20001],s2[20001],len1,len2;
  8 void chen1(int k)
  9 {int i;
 10     memset(c,0,sizeof(c));
 11      for (i=1;i<=len1;i++)
 12      {
 13       c[i]+=s1[i]*k;
 14       if (c[i]>=w)
 15         {
 16             c[i+1]+=c[i]/w;
 17             c[i]%=w;
 18         }
 19      }
 20      if (c[len1+1]) len1++;
 21      while (c[len1]>=w)
 22      {
 23         c[len1+1]+=c[len1]/w;
 24         c[len1]%=w;
 25         len1++;    
 26      }
 27      for (i=1;i<=len1;i++)
 28      {
 29         s1[i]=c[i];
 30      }
 31 }
 32 void chen2(int k)
 33 {int i;
 34     memset(c,0,sizeof(c));
 35      for (i=1;i<=len2;i++)
 36      {
 37       c[i]+=s2[i]*k;
 38       if (c[i]>=w)
 39         {
 40             c[i+1]+=c[i]/w;
 41             c[i]%=w;
 42         }
 43      }
 44      if (c[len2+1]) len2++;
 45      while (c[len2]>=w)
 46      {
 47         c[len2+1]+=c[len2]/w;
 48         c[len2]%=w;
 49         len2++;    
 50      }
 51      for (i=1;i<=len2;i++)
 52      {
 53         s2[i]=c[i];
 54      }
 55 }
 56 void epow1(int x,int y)
 57 {int i;
 58     for (i=1;i<=y;i++)
 59      chen1(x);
 60 }
 61 void epow2(int x,int y)
 62 {int i;
 63     for (i=1;i<=y;i++)
 64      chen2(x);
 65 }
 66 void print1()
 67 {int i,j;
 68     printf("%lld",s1[len1]);
 69     for (i=len1-1;i>=1;i--)
 70     {int k=0;
 71     long long x=s1[i];
 72         while (x)
 73         {k++;
 74             x/=10;
 75         }
 76        for (j=9;j>k;j--)
 77         printf("0");
 78         if (s1[i])
 79         printf("%lld",s1[i]);
 80     }
 81 }
 82 void print2()
 83 {int i,j;
 84     printf("%lld",s2[len2]);
 85     for (i=len2-1;i>=1;i--)
 86     {int k=0;
 87     long long x=s2[i];
 88         while (x)
 89         {k++;
 90             x/=10;
 91         }
 92        for (j=9;j>k;j--)
 93         printf("0");
 94         if (s2[i])
 95         printf("%lld",s2[i]);
 96     }
 97 }
 98 long long gcd(long long a,long long b)
 99 {
100     if (b==0)
101     {
102         return a;
103     }
104      long long r=gcd(b,a%b);
105       return r;
106 }
107 int main()
108 {int T,l,i,n,k;
109 //freopen("ans.out","w",stdout);
110     cin>>T;
111     for (l=1;l<=T;l++)
112     {
113         scanf("%d%d",&n,&k);
114         if (n>k) 
115         {
116             cout<<0<<' '<<1<<endl;
117             continue;
118         }
119         memset(s1,0,sizeof(s1));
120         memset(s2,0,sizeof(s2));
121         s1[1]=1;
122         len1=1;
123        long long x=k-n+1;
124        for (i=1;i<=n;i++)
125        {
126             long long d=gcd(k,x);
127             x/=d;
128              chen1(k/d);
129        } 
130         len2=1;
131         s2[1]=1;
132         epow2(k+1,n-1);
133         chen2(x);
134         print2();
135         cout<<' ';
136         print1();
137         cout<<endl;
138     }
139 }

 



posted @ 2017-07-03 10:45  Z-Y-Y-S  阅读(975)  评论(1编辑  收藏  举报