[CSP-S模拟测试]:简单的玄学(数学)

题目描述

有$m$个在$[0,2^n)$内均匀随机取值的整型变量,球至少有两个变量取值相同的概率。
为了避免精度误差,假设你的答案可以表示成$frac{a}{b}$的形式,(其中$(a,b)=1$),你需要输出$a$和$b$对${10}^6+3$取模后的值。


输入格式

第一行两个正整数$n,m$。


输出格式

一行两个整数,它们的含义如题所述。


样例

样例输入1:

3 2

样例输出1:

1 8

样例输入2:

1 3

样例输出2:

1 1

样例输入3:

4 3

样例输出3:

23 128


数据范围与提示

对于$10\%$的数据,$nm<16$;
对于$30\%$的数据,$nm<64$;
对于$50\%$的数据,$nmleqslant {10}^3$;
对于$70\%$的数据,$mleqslant {10}^6$;
对于$100\%$的数据,$1leqslant nleqslant {10}^{18},2leqslant mleqslant {10}^{18}$。


题解

数学题就要推式子。

显然这个概率就是$dfrac{A_{2^2}^m}{2^{nm}}$,也就是$dfrac{prod limits_{i=2^n-m+1}^{2^n-1}}{2^{n(m-1)}}$。

看起来很恐怖,其实如果$m>{10}^6+3$那么在连乘的过程中肯定会有其中一项是$0$,那么结果就是$0$。

但是我们要输出$gcd(a,b)=1$的分子和分母,所以我们还得约分……

发现我们只能约分出来$2$和$2$的倍数,所以我们考虑如何求出来有多少个$2$。

考虑$a$中$2$的个数和$2^n-a$中$2$的个数相同,所以我们只需要求出$(m-1)!$中$2$的个数即可,可以用一种类似快速幂的思想在$Theta(log m)$的时间复杂度内求出,然后约掉这些$2$就是最简分数啦。

时间复杂度:$Theta(m)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
long long n,m;
long long fz,fm;
long long qpow(long long x,long long y)
{
	long long res=1;
	while(y)
	{
		if(y&1)res=res*x%1000003;
		x=x*x%1000003;
		y>>=1;
	}
	return res;
}
int main()
{
	scanf("%lld%lld",&n,&m);
	n%=1000002;
	int flag=65;
	long long pos=1,fj=0;
	while(flag--)
	{
		pos<<=1;
		if(pos>=m)break;
		fj=(fj+(m-1)/pos)%1000002;
	}
	long long inv=qpow(qpow(2,fj),1000001);
	long long C=qpow(2,n);
	fm=qpow(C,(m-1)%1000002)*inv%1000003;
	if(m<=1000003)
	{
		fz=inv;
		for(int i=1;i<m;i++)
			fz=fz*(C-i+1000003)%1000003;
		fz=(fm-fz+1000003)%1000003;
		printf("%lld %lld",fz,fm);
	}
	else printf("%lld %lld",fm,fm);
	return 0;
}

rp++

原文地址:https://www.cnblogs.com/wzc521/p/11494463.html