1. 程式人生 > >Codeforces 711 E. ZS and The Birthday Paradox(數學)——Codeforces Round #369 (Div. 2)

Codeforces 711 E. ZS and The Birthday Paradox(數學)——Codeforces Round #369 (Div. 2)

[傳送門](http://codeforces.com/contest/711/problem/E) E. ZS and The Birthday Paradoxtime limit per test2 secondsmemory limit per test256 megabytesinputstandard inputoutputstandard 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 2n days in a year. ZS the Coder wants to interview k people from Udayland, each of them has birthday in one of 2n 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

. 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 ≤ n ≤ 1018, 2 ≤ k ≤ 1018), meaning that there are 2n 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 2n days long year equals (A ≥ 0, B ≥ 1, ), print the A and B in a single line.

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

ExamplesInput
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 23 = 8 days in Udayland. The probability that 2 people have the same birthday among 2 people is clearly , so A = 1, B = 8.

In the second sample case, there are only 21 = 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.


題目大意:

一年有 2n(n1018) 天,然後有 k(k1018) 個小朋友,現在問你的是:這 k 個小朋友中至少有兩個

小朋友生日相同的概率是多少,假設這個概率約分後為 pq,輸出 p,q1000003 取模

解題思路:

首先我們來分析一下題目,因為題目中說 至少 兩個小朋友生日相同的概率,那麼我們從反面來考慮,那麼也就是說所有

的小朋友的生日都不相同的概率是多少,那麼我們這個可以列出一個式子:

A(2n,k)(2n)k(1)

那麼我來解釋一下這個式子:首先因為有 k 個小朋友,所以有 k個生日,然後一個小朋友生日是某一天的概率是

12n,所以 k 個小朋友的生日的概率就是 1(2n)k,那麼我們現在保證每個小朋友的生日都不是

相同的,所以就是從 2n 天中選 k 個,然後有 k 種排列,所以就是 A(2n,k),所以我們要做的就是化簡 (1) 式,

那麼我們通過觀察可以得出結論:分子和分母的最大公約數一定是 2i,所以我們只要將 GCD 求出來了,然後分子分母分

別除以最大公約數就行了,因為分子的 2 肯定是比分母少的,所以只要求出分子中有多少 2 就行了,這個問題就是相當於

n! 後面有多少個 0,因為分子展開為:

A(2n,k)=(2n)(2n1)(2n2)...(2nk+1)

首先可以先將 2n 與 分母約分一下,然後找的是 (k1)! 有多少個 2 ,每次除以 2,這個就不細說了,那麼找到

GCD 以後,我們就進行計算,因為分母好操作就是 n(k1) 注意用快速乘法小心爆 longlong,然後就是分子了,其

實我們仔細觀察一下的話,會發現如果 MOD<k 的 時候分子一定是 0,因為分子一直是 (2ni) 這樣的,剩下的暴

力做就行了,得到分子之後別忘記除以 GCD,這個地方就要通過逆元來實現了,還有需要注意的是當 2n<k 的時候 直

接輸出 11 就行了 最後不要忘記 概率是 1ans

MyCode

/**
2016 - 08 - 30 晚上
Author: ITAK

Motto:

今日的我要超越昨日的我,明日的我要勝過今日的我,
以創作出更好的程式碼為目標,不斷地超越自己。
**/

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
#include <set>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int INF = 1e9+5;
const int MAXN = 1e3+5;
const LL MOD = 1e6+3;
const double eps = 1e-7;
const double PI = acos(-1);
using namespace std;
LL Scan_LL()///輸入外掛
{
    LL res=0,ch,flag=0;
    if((ch=getchar())=='-')
        flag=1;
    else if(ch>='0'&&ch<='9')
        res=ch-'0';
    while((ch=getchar())>='0'&&ch<='9')
        res=res*10+ch-'0';
    return flag?-res:res;
}
int Scan_Int()///輸入外掛
{
    int res=0,ch,flag=0;
    if((ch=getchar())=='-')
        flag=1;
    else if(ch>='0'&&ch<='9')
        res=ch-'0';
    while((ch=getchar())>='0'&&ch<='9')
        res=res*10+ch-'0';
    return flag?-res:res;
}
void Out(LL a)///輸出外掛
{
    if(a>9)
        Out(a/10);
    putchar(a%10+'0');
}
LL Multi(LL a, LL b)
{
    LL ans = 0;
    while(b)
    {
        if(b & 1)
            ans = (ans+a)%(MOD-1);
        b>>=1LL;
        a = (a+a)%(MOD-1);
    }
    return ans;
}
LL quick(LL a, LL b)
{
    LL ans = 1;
    while(b)
    {
        if(b & 1)
            ans = (ans*a) % MOD;
        b>>=1LL;
        a = (a*a) % MOD;
    }
    return ans;
}
void Exgcd(LL a, LL b, LL &x, LL &y)
{
    if(b == 0)
    {
        x = 1;
        y = 0;
        return;
    }
    LL x1, y1;
    Exgcd(b, a%b, x1, y1);
    x = y1;
    y = x1 - (a/b)*y1;
}
int main()
{
    LL Inv, y;
    Exgcd(2, MOD, Inv, y);
    Inv = (Inv%MOD+MOD)%MOD;
    LL n, k;
    while(cin>>n>>k)
    {
        if(n < 63LL)
        {
            if(k > (1LL<<n))
                puts("1 1");
            else
            {
                LL ans = 0, fm = k, tmp;
                fm--;
                while(fm)
                {
                    fm>>=1LL;
                    ans += fm;
                }
                fm = k-1LL;
                fm = Multi(n, fm);
                fm = (fm-ans)%(MOD-1);
                fm = (fm%(MOD-1)+(MOD-1))%(MOD-1);
                fm = quick(2LL, fm);
                if(k > MOD)
                {
                    cout<<fm<<" "<<fm<<endl;
                    continue;
                }
                tmp = quick(2LL, n);
                LL fz = 1;
                for(LL i=1; i<k; i++)
                    fz = fz*(tmp-i)%MOD;
                fz = (fz%MOD+MOD)%MOD;
                fz = fz*quick(Inv, ans)%MOD;
                fz = fm - fz;
                fz = (fz%MOD+MOD)%MOD;
                cout<<fz<<" "<<fm<<endl;
            }
        }
        else
        {
            LL ans = 0, fm = k, tmp;
            fm--;
            while(fm)
            {
                fm>>=1LL;
                ans += fm;
            }
            /** 2^ans 是最大公約數 **/
            fm = k-1LL;
            fm = Multi(n, fm);
            fm = (fm-ans)%(MOD-1);
            fm = (fm%(MOD-1)+(MOD-1))%(MOD-1);
            fm = quick(2LL, fm);
            if(k > MOD)
            {
                cout<<fm<<" "<<fm<<endl;
                continue;
            }
            tmp = quick(2LL, n);
            LL fz = 1;
            for(LL i=1; i<k; i++)
                fz = fz*(tmp-i)%MOD;
            fz = fz*quick(Inv, ans)%MOD;
            fz = fm - fz;
            fz = (fz%MOD+MOD)%MOD;
            cout<<fz<<" "<<fm<<endl;
        }
    }
    return 0;
}