Codeforces Round #334 (Div. 2) E(抽屉原理+逆元+费马小定理 )

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/guhaiteng/article/details/52435054

传送门:E. ZS and The Birthday Paradox

描述:

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;
}


展开阅读全文

没有更多推荐了,返回首页