[Codeforces #369 (Div. 2)E. ZS and The Birthday Paradox]勒让德定理+逆元
题目链接:[Codeforces #369 (Div. 2)E. ZS and The Birthday Paradox]
题意描述:这个题目是基于生日悖论为背景的一道题目。某个星球一年有
2N
天,有K个人,问存在两个或两个以上的人同一天生日的概率,要求写成约分之后的分数形式。最后将分子和分母同时对
106+3
取模。
解题思路:首先很容易列出最初的式子。
∏i=Ki=1(2N−i+1)(2N)K=∏i=Ki=2(2N−i+1)2N∗(K−1)
。
然后就是考虑对这个式子进行约分。观察分母可以发现分子分母的最大公约数肯定是 2的幂次方。我们不妨设分子分母的最大公约数是 2t 。
观察分子,由于 gcd(2N−x,2N)=gcd(x,2N)=2y ,也就是说。 2N−x 与 x 的素因子标准分解式中素数2的指数相同,所以
由 勒让德定理可以求出 (K−1)! 的素因子标准分解式素数2的指数,从而求出分子分母的 gcd 。复杂度是 O(log(k)) .
勒让德定理
在正数n!的素因子标准分解式中,素数p的指数记作 Lp(n!) , 则Lp(n!)=∑k≥1⌊>npk⌋
求出 gcd 之后就是让分子分母除以 gcd 然后取模,这里我们就可以使用乘以 gcd 的逆元然后在取模。
- 当 a ,
p 互斥时, ap−1≡1modp 。- 当 a ,
p 互斥时, ap−2≡1amodp 。
#include <bits/stdc++.h>
using namespace std;
#define FIN freopen("input.txt","r",stdin)
#define FOUT freopen("output.txt","w",stdout)
#define fst first
#define snd second
typedef __int64 LL;
const LL MOD = 1e6 + 3;
LL N, K;
LL A, B, t, x, gcd, inv;
LL quick_pow(LL a, LL b, LL mod) {
LL ret = 1;
while(b > 0) {
if(b & 1) ret = ret * a % mod;
a = a * a % mod;
b >>= 1;
}
return ret;
}
int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif // ONLINE_JUDGE
while(~scanf("%I64d %I64d", &N, &K)) {
if (N < 64 && K > (1LL << N)) {
printf("1 1\n");
continue;
}
t = 0;
for (LL i = 2; i <= (K - 1); i <<= 1) {
t += (K - 1) / i;
}
gcd = quick_pow(2LL, t, MOD);
x = quick_pow(2LL, N, MOD);
A = B = 1;
for (LL i = 1; i <= (K - 1); i ++) {
A = A * (x - i + MOD) % MOD;
if(!A) break;
}
inv = quick_pow(gcd, MOD - 2, MOD);
A = A * inv % MOD;
B = quick_pow(x, K - 1, MOD);
B = B * inv % MOD;
A = (B - A + MOD) % MOD;
printf("%I64d %I64d\n", A, B);
}
return 0;
}