1. 程式人生 > >Codeforces Round #334 (Div. 2) E(抽屜原理+逆元+費馬小定理 )

Codeforces Round #334 (Div. 2) E(抽屜原理+逆元+費馬小定理 )

描述:
E. 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 23people, 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 ≥ 0B ≥ 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.

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


題意:

有2^n天,k個人,求至少2個人生日相同的概率,要求分子分母約分後再對1e6+3取模。

思路:

正難則反,我們就該從反面考慮考慮

"任意兩個人的生日都不在同一天"的情況數相當於從天中挑選k天進行隨意排列

當k>時,由抽屜原理至少有兩個人的生日在同一天的概率為100%,故結果輸出"1 1"

那麼剩下的情況,即k≤,"至少有兩個人的生日在同一天的概率"=1-"任意兩個人的生日都不在同一天"

∴"至少有兩個人的生日在同一天的概率"=


下面我們來計算這一部分:

因為分母很明顯是以2為底的冪,故分子和分母的GCD值肯定也是以2為底的冪,暫時記為

那接下來,問題的關鍵就是求分子式中有多少個2

對於分子中第i項分子式,中有n個2,那該項分子式中2的個數就取決於i

例如i=4時,該項分子式有2個2;i=16時,該項分子式有4個2

那最終把每項分子式中2的個數加起來便是tmp值,故約分之後,結果為


因為結果需要取模,於是便涉及到了除法取模,然後理所應當的就需要用到乘法逆元


那麼mod p 該怎麼計算呢?直接快速冪顯然不行,因為指數部分已經超出了__int64的範圍

這時候就需要想到費馬小定理,這樣就可以進行降冪,然後再快速冪求解

逆元部分也是如此,可以通過費馬小定理降冪之後再求解

那分子部分呢?

觀察,可以發現,其實分子就是k-1個連續整數的乘積

那麼當k-1≥mod時,k-1個連續整數中必有一個能被mod整除,這就意味著取模之後結果為0,那k-1個連續整數的乘積就是0

而當k-1<mod時,因為mod的值不大,所以我們可以暴力迴圈求出分子

程式碼:
#include <bits/stdc++.h>
#define ll __int64
using  namespace  std;

template<class T> void read(T&num) {
    char CH; bool F=false;
    for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar());
    for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar());
    F && (num=-num);
}

const ll mod=1e6+3;

ll pow_mod(ll x, ll n){
    ll res=1;
    while(n>0){
        if(n&1)res=res*x%mod;
        x=x*x%mod;
        n>>=1;
    }
    return res;
}

bool ok(ll n, ll k){
  ll s=1;
  for(int i=1; i<=n ;i++){
    s*=2;
    if(s>=k)return false;
  }
  return true;
}

int  main(){

  ll n,k;
  read(n);read(k);
  if(ok(n,k)){
    puts("1 1");
    return 0;
  }
  ll A,B,GCD,tmp,i;
  B=pow_mod(2,  n%(mod-1)*(  (k%(mod-1)-1+(mod-1))%(mod-1)  )%(mod-1)   );
  for(tmp=0,i=2; i<=k-1; i*=2)tmp+=(k-1)/i;
  GCD=pow_mod(2, tmp%(mod-1)*(mod-2)%(mod-1));
  B=B*GCD%mod;
  if(k-1>=mod)printf("%I64d %I64d\n",B,B);
  else{
    A=1;
    for(i=1; i<=k-1; i++)
      A=A*(( pow_mod(2,n%(mod-1)) -i+mod)%mod) %mod;
    A=A*GCD%mod;
    printf("%I64d %I64d\n",(B-A+mod)%mod,B);
  }
  return 0;
}