Codeforces Round #369 (Div. 2)E

ZS and The Birthday Paradox

题目:一年有2^n天,有k个人,他们的生日有冲突的概率是多少?答案用最简分数表示,分子分母对1e6+3取模。1 ≤ n ≤ 10^18, 2 ≤ k ≤ 10^18。

答案为 1 - A(2^n,k) / (2^n)^k,分子与分母的gcd必定为2^i。计算A(2^n,k)=(2^n) * (2^n-1) * ... * (2^n-k+1)含多少个因子2,相当于计算0~k-1中总共有多少个因子2。

因为分子乘以了模mod后就永远是0了,所以可以O(mod)的算出分子。求出gcd后乘上gcd的逆元就可以了。

 1 #include <map>
 2 #include <set>
 3 #include <stack>
 4 #include <queue>
 5 #include <ctime>
 6 #include <vector>
 7 #include <cstdio>
 8 #include <cctype>
 9 #include <cstring>
10 #include <cstdlib>
11 #define eps 1e-15
12 #define PI acos(-1)
13 #define INF 100000007
14 #define MAX(a,b) (a>b?a:b)
15 #define MIN(a,b) (a<b?a:b)
16 #define mem(a) memset(a,0,sizeof(a))
17 #define N 400005
18 #define P 1000003
19 long long n,k,i,p,q,x,ans,kk,ny;
20 
21 long long pow(long long a,long long b)
22 {
23     long long ans=1;
24     while (b>0)
25     {
26         if (b&1==1)
27             ans=(ans*a)%P;
28         b>>=1;
29         a=(a*a)%P;
30     }
31     return ans;
32 }
33 int main()
34 {
35     scanf("%I64d%I64d",&n,&k);
36     if (n<63)
37     {
38         if ((1ll<<n)<k)
39         {
40             printf("1 1\n");
41             return 0;
42         }
43 
44     }
45     x=pow(2,n);
46     p=1;
47     for (i=1;i<k;i++)
48     {
49         x--;
50         p=(p*x)%P;
51         if (p==0) break;
52     }
53     kk=k-1;
54     while (kk>0)
55     {
56         ans+=kk/2;
57         kk=kk>>1;
58     }
59     ny=pow(pow(2,P-2),ans);
60     p=(p*ny)%P;
61     q=(pow(pow(2,n),k-1)*ny)%P;
62     p=q-p;
63     if (p<0)p+=P;
64     printf("%I64d %I64d\n",p,q);
65     return 0;    
66 }
View Code
#WhenWhoProblemLangVerdictTimeMemory
20280606 2016-08-30 16:20:59 lbz007 E - ZS and The Birthday Paradox GNU C++ Accepted 31 ms 0 KB

 

posted @ 2016-08-31 15:20  lbz007  阅读(163)  评论(0编辑  收藏  举报
Live2D