• Codeforces 711E ZS and The Birthday Paradox


    传送门
    time limit per test 2 seconds
    memory limit per test 256 megabytes
    input standard input
    output standard output

    ZS the Coder has recently found an interesting concept called the Birthday Paradox. It states that given a random set of $23$ people, there is around $50%$ chance that some two of them share the same birthday. ZS the Coder finds this very interesting, and decides to test this with the inhabitants of Udayland.

    In Udayland, there are $2^n$ days in a year. ZS the Coder wants to interview $k$ people from Udayland, each of them has birthday in one of $2^n$ days (each day with equal probability). He is interested in the probability of at least two of them have the birthday at the same day.

    ZS the Coder knows that the answer can be written as an irreducible fraction $dfrac{A}{B}$. He wants to find the values of $A$ and $B$ (he does not like to deal with floating point numbers). Can you help him?

    Input

    The first and only line of the input contains two integers $n$ and $k$ ($1 le n le 10^18, 2 le k le 10^18$), meaning that there are $2^n$ days in a year and that ZS the Coder wants to interview exactly $k$ people.

    Output

    If the probability of at least two $k$ people having the same birthday in $2^n$ days long year equals ($A ge 0, B ge 1, gcd(A,B)=1$), print the $A$ and $B$ in a single line.

    Since these numbers may be too large, print them modulo $10^6 + 3$. Note that $A$ and $B$ must be coprime before their remainders modulo $10^6 + 3$ are taken.

    Examples

    Input

    3 2

    Output

    1 8

    Input

    1 3

    Output

    1 1

    Input

    4 3

    Output

    23 128

    Note

    In the first sample case, there are $2^3 = 8$ days in Udayland. The probability that $2$ people have the same birthday among $2$ people is clearly $frac{1}{8}$ , so $A = 1, B = 8$.

    In the second sample case, there are only $2^1 = 2$ days in Udayland, but there are $3$ people, so it is guaranteed that two of them have the same birthday. Thus, the probability is $1$ and $A = B = 1$.


    Solution

    首先注意到$10^6+3$是个素数.
    不难想到求任意两人生日都不冲突的概率更为简单, 答案是$dfrac{A_{2n}{k}}{2^{nk}}$, 展开化简得
    $$ frac{(2n-1)(2n-2)cdots(2n-(k-1))}{2{n(k-1)}} $$
    这里我们需要注意:
    $$dfrac{a}{b}既约Longleftrightarrow dfrac{a}{b-a}既约, (b>a)$$
    因为$gcd(a, b)=gcd(a, b-a)$.

    接着要对此式进行约分, 也就是求分子的素因子分解形式中2的幂次. 这里有个key observation:

    $$2^n-x中2的幂次和x中2的幂次相同.$$

    所以问题转化成求$(k-1)!$中所包含的2的幂次.
    而$n!$中包含的素数$p$的幂次, 记作$ u_p(n!)$, 为:

    $$ u_p(n!)=sum_{ige 1}[frac{n}{p^i}]$$

    上式也称作Legendre's formula.
    注意: 如果$p$不是素数, 这个结论是不成立的.

    Implementation

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    
    // return the max k s.t. p^k | n!
    LL get_exponent(LL n, int p){
        LL res=0;
        for(LL x=p; n>=x; res+=n/x, x*=p);
        return res;
    }
    
    LL Pow(LL x, LL n, int p){
        LL res=1;
        for(; n; x*=x, x%=p, n>>=1)
            if(n&1) res*=x, res%=p;
        return res;
    }
    // return 2^{(k-1)*n}
    LL calc2(LL n, LL k, int p){
        return Pow(Pow(2, k-1, p), n, p);
    }
    // x cannot be divided by p
    LL inv(LL x, int p){
        return Pow(x, p-2, p);
    }
    // A(n, k)%p, p is small
    // n>=k
    LL calc3(LL n, LL k, int p){
        if(k>=p) return 0;
        LL res=1;
        for(; k; ){
            res*=n, res%=p;
            if(n==0) break;
            --k, --n;
        }
        return res;
    }
    
    int main(){
        LL n, k;
        cin>>n>>k;
        int p=1000003;
    
        if(log2(k)>n){
            puts("1 1");
        }
        else{
            LL cnt=get_exponent(k-1, 2);    //error-prone
            LL x=Pow(2, cnt, p);
    
            LL y=(Pow(2, n, p)+p-1)%p;
            LL t=inv(x, p);
            LL num=calc3(y, k-1, p)*t%p;
            LL den=calc2(n, k, p)*t%p;
    
            num=(den-num+p)%p;  //error-prone
            cout<<num<<' '<<den<<endl;
        }
    }
    

    Pitfalls

    最近写代码总是犯各种各样的傻逼错误. 比如这次我把函数calc2()中的return Pow(Pow(2, k-1, p), n, p);写成了Pow(Pow(2, k-1, p), n, p);. 这样在本地竟然把3个样例都过了. 然后交上去竟然WA on T1.
    历尽千辛万苦才找到bug. 我的编译器(g++ 5.4.0)没报错, 可能是自动识别了这个错误. 避免这个问题的方法是编译时加上-Wall选项.
    g++ main.cpp -o main -Wall -std=c++14 && ./main <in

  • 相关阅读:
    级数问题
    放苹果
    _WIN32_WINNT not defined错误 解决办法
    日期大写
    金额大写转换
    选择屏幕字段不允许直接输入…
    OO面向对象ALV小测试
    判断是否有人在操作某张表,并获取…
    屏幕中设置焦点
    前导零
  • 原文地址:https://www.cnblogs.com/Patt/p/5861779.html
Copyright © 2020-2023  润新知