2227: [Zjoi2011]看电影(movie)

来源:互联网 发布:摩卡软件招聘 编辑:程序博客网 时间:2024/06/05 16:23

2227: [Zjoi2011]看电影(movie)

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 801  Solved: 402
[Submit][Status][Discuss]

Description

到了难得的假期,小白班上组织大家去看电影。但由于假期里看电影的人太多,很难做到让全班看上同一场电影,最后大家在一个偏僻的小胡同里找到了一家电影院。但这家电影院分配座位的方式很特殊,具体方式如下: 1. 电影院的座位共有K个,并被标号为1…K,每个人买完票后会被随机指定一个座位,具体来说是从1…K中等可能的随机选取一个正整数,设其为L。 2. 如果编号L的座位是空位,则这个座位就分配给此人,否则将L加一,继续前面的步骤。 3. 如果在第二步中不存在编号L的座位,则该人只能站着看电影,即所谓的站票。小白班上共有N人(包括小白自己),作为数学爱好者,小白想知道全班都能够有座位的概率是多少。

Input

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

Output

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

Sample Input

3
1 1
2 1
2 2

Sample Output

1 1
0 1
3 4

【数据范围】
对于100%的数据 T<=50,N,K<=200


HINT

Source

Day1&IPSC2009第G题

[Submit][Status][Discuss]




思维非常好的题。。。。可惜想不到。

正面去做的话,无论统计合法概率还是不合法概率都很难。

先考虑特殊的,,n > k 概率一定为0,否则,如果n == 1,概率一定为1

剩下的一般情况,新增一个座位k + 1,把这k + 1个座位连成环,这样无论怎么选,总是合法的

这样一共就是(k+1)^n种选法。对于每种选法,因为是个环,编号可以绕一圈

也就是说,每种选法实际上重复了(k+1)次。因此,本质不同的选法是(k+1)^(n-1)

对于每种选法,由于k+1>n,因此,安排完座位后剩下k + 1 - n个座位,

随意删去一个座位,破环成链就是一种合法方案了

因此,概率统计为(k+1)^(n-1)*(k+1-n) / k^n

分子分母都可能很大,筛出所有质因数,然后上下约分,再做高精度乘法

#include<iostream>#include<cstring>#include<vector>#include<queue>#include<algorithm>#include<cmath>#include<cstdio>#include<bitset>using namespace std;typedef long long LL;const LL mo = 100000000;const int maxn = 200;struct data{LL a[120]; int len; data(){len = 0; memset(a,0,sizeof(a));}data operator *(const data &b){data c; int le = len + b.len;for (int i = 0; i < len; i++)for (int j = 0; j < b.len; j++){c.a[i+j] += a[i]*b.a[j];c.a[i+j+1] += c.a[i+j] / mo;c.a[i+j] %= mo;}c.len = c.a[le-1]?le:le-1;return c;}data operator *(const LL &k){data c;for (int i = 0; i < len; i++){c.a[i] += a[i]*k;c.a[i+1] += c.a[i] / mo;c.a[i] %= mo;}c.len = c.a[len]?len+1:len;return c;}}mi[50][1201];int T,n,k,tot,pri[maxn],A[50],B[50];bool not_pri[maxn];void pt(int x,int res){if (res == 1) {printf("%d",x); return;}pt(x / 10,res - 1); printf("%d",x % 10);}void Print(data K){printf("%lld",K.a[K.len-1]);for (int i = K.len - 2; i >= 0; i--) pt(K.a[i],8);}void Add(int *F,int num,int ti){for (int i = 1; i <= tot; i++){if (pri[i] > num) return;if (num % pri[i] != 0) continue;while (num % pri[i] == 0) F[i] += ti,num /= pri[i];}}int main(){#ifdef DMCfreopen("DMC.txt","r",stdin);#endiffor (int i = 2; i < maxn; i++){if (!not_pri[i]) pri[++tot] = i;for (int j = 1; j <= tot; j++){int Nex = i*pri[j];if (Nex >= maxn) break;not_pri[Nex] = 1;if (i % pri[j] == 0) break;}}for (int i = 1; i <= tot; i++){mi[i][0].len = mi[i][0].a[0] = 1;for (int j = 1; j <= 1200; j++)mi[i][j] = mi[i][j-1]*pri[i];}cin >> T;while (T--){scanf("%d%d",&n,&k);if (n > k) puts("0 1");else if (n == 1) puts("1 1");else{memset(A,0,sizeof(A)); memset(B,0,sizeof(B));Add(A,k + 1,n - 1); Add(A,k + 1 - n,1); Add(B,k,n); data C,D; C.len = C.a[0] = D.len = D.a[0] = 1;for (int i = 1; i <= tot; i++){if (A[i] >= B[i]) A[i] -= B[i],B[i] = 0;else B[i] -= A[i],A[i] = 0;if (A[i]) C = C*mi[i][A[i]];if (B[i]) D = D*mi[i][B[i]];}Print(C); printf(" "); Print(D); puts("");}}return 0;}

0 0
原创粉丝点击