Solution
原题最后的答案比较难求,所以我们可以反方向思考:只需要求出所有人生日不同的概率。
显然这个概率为 (dfrac{A_{2^n}^m}{2^{nm}}=dfrac{prod_{i=2^n-m+1}^{2^n-1}}{2^{n(m-1)}}) 。
分母部分用快速幂即可,而分子部分需要我们思考一下,因为模数为 (10^6+3) ,当 (m) 大于模数时,分子的因数必有一项为模数的倍数,答案可输出 (0) ,其他情况暴力求解即可。
但是,这个题还有一个需要注意的地方是分数的约分。因为分母为 (2) 的幂,所以找出分子中 (2) 的幂次即可。这里用到了 (Legendre's~formula) 。因为对于所有 (1leq aleq 2^n) ,都有 (a) 与 (2^n-a) 的 (2) 的幂次相同,所以求出 ((m-1)!) 中的 (2) 的次数就好了。
时间复杂度: (O(log k+log n))
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int mod=1e6+3;
ll n,k,num=0,fz=1,fm=1;
ll fpow(ll a,ll b){
ll res=1;
while(b){
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
int main(){
scanf("%lld%lld",&n,&k);
num=1;
while((1LL<<num)<k) num++;
if(num>n){
printf("1 1");
return 0;
}
num=0;
for(ll i=k-1;i>=1;i>>=1) num+=(i>>1);
ll a=fpow(2,n);
fz=1;
for(int i=1;i<k;i++){
fz=(ll)fz*(a-i+mod)%mod;
if(fz==0) break;
}
fm=fpow(a,k-1);
int inv=fpow(fpow(2,num),mod-2);
fz=(ll)fz*inv%mod,fm=(ll)fm*inv%mod;
fz=(fm-fz+mod)%mod;
printf("%lld %lld",fz,fm);
return 0;
}