您的位置:首页 > 其它

[Codeforces #369 (Div. 2)E. ZS and The Birthday Paradox]勒让德定理+逆元

2016-09-02 01:36 483 查看

[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的指数相同,所以∏i=Ki=2(2N−i+1)的素因子标准分解式中,素数2的指数个数与∏i=Ki=2(i−1)即(K−1)!的指数相同。

勒让德定理可以求出(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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: