codeforces 711E. ZS and The Birthday Paradox 概率

已知一年365天找23个人有2个人在同一天生日的概率 > 50%

给出n,k ,表示现在一年有2^n天,找k个人,有2个人在同一天生日的概率,求出来的概率是a/b形式,化到最简形式,由于a,b可能非常大,对a,b分别%(10^6+3)

注意,这道题是先化到最简,再分别取模

首先,特判 k > 2^n 时,a = 1,b = 1

没有2个人同一天生日的概率为:

2^n * (2^n - 1) * ... * (2^n - k + 1) / 2^(nk)

所以a,b化简之前分别是:

a = 2nk-n - (2n - 1) * (2n - 2) * ... * (2n - k + 1)

b = 2nk-n

化简,就是要求gcd(a,b)

可以肯定,gcd(a,b)肯定是2d这种形式

由于k < 2n,d实际上就等于(k-1)!分解素因子后2的个数

如果k >= P,化简取模后有a = b,(但是取模后不能再继续化简为a = b = 1)

如果k < P,log(k)求得d,则:

b = 2nk-n-d,快速幂可求,由于n * k会超过long long,可以先 % phi(P),欧拉定理

a = 2nk-n-d - (2n - 1) * (2n - 2) * ... * (2n - k + 1) / 2d

后面这个可以先暴力O(k)求,再乘以2d的逆元

注意 a = (a + P) % P防止a < 0 的情况

代码:

  //File Name: cf711E.cpp
  //Created Time: 2017年01月06日 星期五 00时05分30秒

#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int P = (int)1e6 + 3;
LL qp(LL x,LL y){
    LL res = 1;
    for(;y>0;y>>=1){
        if(y & 1) res = res * x % P;
        x = x * x % P;
    }
    return res;
}
LL cal_phi(LL n){
    LL res = n;
    for(int i=2;i*i<=n;++i){
        if(n % i == 0){
            res -= res / i;
            while(n % i == 0)
                n /= i;
        }
    }
    if(n > 1) res -= res / n;
    return res;
}
void solve(LL n,LL k,LL &a,LL &b){
    LL now = 1;
    for(LL j=1;j<=n;++j){
        now *= 2;
        if(now >= k) break;
    }
    if(now < k) a = 1,b = 1;
    else{
//        puts("fffff");
        LL d = 0;
        now = k - 1;
        while(now >= 2){
            d += now / 2;
            now /= 2;
        }
        LL phi = P - 1;
        b = qp(2,((n % phi) * (k % phi) - n % phi - d % phi + 2 * phi) % phi);
        if(k >= P) a = b;
        else{
            now = qp(2,n % phi);
            a = 1;
            for(LL i=1;i<k;++i)
                a = (now - i + P) % P * a % P;
            now = qp(2,d % phi);
            a = a * qp(now,P - 2) % P;
            a = (b - a + P) % P;
        }
    }
}
int main(){
    LL n,k;
    cin >> n >> k;
    LL a,b;
    solve(n,k,a,b);
    printf("%lld %lld\n",a,b);
    return 0;
}
时间: 2024-12-24 13:11:42

codeforces 711E. ZS and The Birthday Paradox 概率的相关文章

Codeforces 711E ZS and The Birthday Paradox(乘法逆元)

[题目链接] http://codeforces.com/problemset/problem/711/E [题目大意] 假设一年有2^n天,问k个小朋友中有两个小朋友生日相同的概率. 假设该概率约分后为 p / q ,输出p , q对1000003取模的解. [题解] 当k比天数要大时是肯定成立的,否则答案为1-A(2n,k) / (2n)k, 考虑A(2n,k)=2n*(2n-1)*……*(2n-k+1),所以分子和分母的最大公约数是2的幂次,暴力计算分子分母,以及计算最大公约数的逆元,就可

Codeforces 453A Little Pony and Expected Maximum 概率题Orz

题目链接:点击打开链接 #include <stdio.h> #include <iostream> #include <algorithm> using namespace std; #define INF 0x3f3f3f3f #define eps 1e-8 #define pi acos(-1.0) typedef long long ll; int main() { int i, j; double m,n; while(cin>>m>>

Codeforces 148D 一袋老鼠 Bag of mice | 概率DP 水题

除非特别忙,我接下来会尽可能翻译我做的每道CF题的题面! Codeforces 148D 一袋老鼠 Bag of mice | 概率DP 水题 题面 胡小兔和司公子都认为对方是垃圾. 为了决出谁才是垃圾,大哥拿来了一袋老鼠,其中有w只白老鼠和b只黑老鼠.胡小兔先抓,先抓到白老鼠的人赢. 每次学姐抓完老鼠之后,总会有另外一只老鼠从袋子里自己跑出来(这只老鼠不算任何人抓的),而胡小兔抓老鼠时则不会发生这样的事. 每次袋子里的每只老鼠被抓到的概率相等,当有一只老鼠跑出来的时候,每只老鼠跑出来的几率也相

LightOJ1104---Birthday Paradox (概率)

Sometimes some mathematical results are hard to believe. One of the common problems is the birthday paradox. Suppose you are in a party where there are 23 people including you. What is the probability that at least two people in the party have same b

CodeForces 54C-First Digit Law(数位,概率dp)

题意: 给你n个区间,在每个区间里各取一个数(随机取),求这n个数中超过K%的数是首位为1数的概率 分析: dp[i][j]取前i个数,有j个是首位为1的数的概率 易知,dp[i][j]=dp[i-1][j]*(1-p[i])+dp[i-1][j-1]*p[i]; 现在关键是求p[i],第i个区间首位为1的数出现的概率,用数位统计一下即可 #include <map> #include <set> #include <list> #include <cmath&g

Codeforces 54C First Digit Law 数位dp+概率dp

题目链接:点击打开链接 题意: 给定n个区间 下面n个区间 从每个区间中任选一个数.则一共选出了n个数 给出K(<=100) 问选出的n个数中 最高位是1的个数 占n个数的百分之K以上的概率是多少. 先求出对于第i个区间 ,选出的数最高位是1的概率P[i] dp[i][j] 表示前i个数选了j个最高位是1的概率. ////////////////////////////////////// //**********************************// //* ======= la

codeforces 711E 数学

计算1-(2^n-1)*...*(2^n-(k-1))/(2^n(k-1)). 先算公约数,可以看出公约数只能是2的n次幂,求每个分子和2的n次幂的最大公约数,因为gcd(a,b)=gcd(b-a,a),所以直接求2^n和(k-1)!的公约数,然后同除就行.这里有勒让德定理:在正数n!的素因子标准分解式中,素数p的指数记作,则.然后就能算出有多少2的约数,一除就行. 最后如果是大于最多的天数,就直接输出1.

[Codeforces 839C] Journey

[题目链接] http://codeforces.com/contest/839/problem/C [算法] 概率DP 时间复杂度 : O(N) [代码] #include<bits/stdc++.h> using namespace std; #define MAXN 100010 int tot , n; int head[MAXN]; bool visited[MAXN]; double f[MAXN]; struct edge { int to , nxt; } e[MAXN <

Codeforces Div.301D Bad Luck Island(概率dp+记忆化搜索)

一道概率dp问题. 题目链接:http://codeforces.com/contest/540/problem/D 题目大意:一个岛上有r个石头,s个剪子,p个布,他们之间随机挑出两个相遇,如果不是相同物种,就会有一个消失,分别求出最后这座岛上只剩下一个物种的概率. 我们用dp[i][j][k]来存储i个石头,j个剪刀,k个布时,某物种的存活概率,共dp三次,算出三个物种分别的概率. 首先,我们需要把对应想求的物种概率初始化,这里以石头为例,那么对于i从1到r,不难理解dp[i][0][0]=