Codeforces 711E ZS and The Birthday Paradox 数论(Legendre's定理)

点击打开链接

题意:一年有s=2^n天,有k个人 问至少有两个人生日在同一天的概率?(答案%mod)
n,k<=1e18


算对立事件 任意两人生日都不同的概率 ( (2^n-1)*(2^n-2)*...*(2^n-(k-1)) )  /(2^(n*(k-1))
n,k<=1e18都非常大,尝试将分子分母同时约去gcd(A,B),分母是2的幂次 则gcd也肯定为2^i,找到最大i
分子可以展开成A=f(p)*2^n+(k-1)! f(p)为某个多项式 
则gcd2^i满足2^i|2^n && 2^i|(k-1)! 根据Legendre's定理(其实就是算因子2在k!中出现多少次) 求出d=2^i
对于分母 可以直接消掉d  对于分子(2^n-1)*(2^n-2)*...*(2^n-(k-1)) 
若k>mod 则分子显然为0(因为分子为mod个连续的数相乘,至少有一个数为mod的倍数)
若k<mod mod=1e6+3 暴力算出分子后乘上逆元即可.总的复杂度为O(mod+log(k)+log(n))

#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const int N=2e5+20;
const ll mod=1e6+3;
ll n,k;
ll powmod(ll x,ll n)
{
	ll s=1;
	while(n)
	{
		if(n&1)
			s=(s*x)%mod;
		x=(x*x)%mod;
		n>>=1;
	}
	return s;
}
ll inverse(ll x)
{ 
	return powmod(x,mod-2);
}
int main()
{
	while(cin>>n>>k)
	{
		ll pw=0,d;
		if(n<=63 && k>(1ll<<n))
		{
			puts("1 1");
			continue;
		}
		ll A=1,B;
		//if(k-1>=mod)
		//	A=0;
		ll x=2;
		//ÕÒµ½·Ö×ӺͷÖĸµÄgcd
 		while(x<=k-1)
 			pw+=(k-1)/x,x=x*2ll;
		d=powmod(2ll,pw);
		ll res=1,y=powmod(2,n);
 		for(ll i=1;i<=k-1;i++)
 		{
			res=(res*(y-i+mod)%mod)%mod;
 			if(res==0)//×î¶à×ömod-1´Î 
 				break;
		}
		res=(res*inverse(d))%mod;
		A=res;
	
		B=powmod(2ll,n)%mod;
		B=powmod(B,k-1)%mod;
		B=(B*inverse(d))%mod;
		
		A=(B-A+mod)%mod;
		cout<<A<<' '<<B<<endl;
	}
	return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值