题意:
定义 n d m o d d = m × d x d m o d d = m m o d d n~dmod~d = m × d^x~dmod~d = m~mod~d n dmod d=m×dx dmod d=m mod d,其中 n = m × d x n = m × d^x n=m×dx 且 d d d 不是 m m m 的因子。先给定 M , N , D M, N, D M,N,D,求 C ( M , N ) d m o d D C(M, N)~dmod~D C(M,N) dmod D。 ( N ≤ M ≤ 4 × 1 0 18 , 2 ≤ D ≤ 1.6 × 1 0 7 ) (N \leq M \leq 4 × 10^{18}, 2 \leq D \leq 1.6 × 10^7) (N≤M≤4×1018,2≤D≤1.6×107)
链接:
https://vjudge.net/problem/Gym-102460M
解题思路:
由于习惯,将题目里的
N
M
NM
NM 对调一下,即求
C
(
N
,
M
)
d
m
o
d
D
C(N, M)~dmod~D
C(N,M) dmod D。记
N
/
D
N/D
N/D 为
N
N
N 去掉所有
D
D
D 因子后所得数,当
D
D
D 为质数时,
C
(
N
,
M
)
=
N
!
M
!
∗
(
N
−
M
)
!
=
N
!
/
D
M
!
/
D
∗
(
N
−
M
)
!
/
D
∗
D
K
C(N, M) = \cfrac{N!}{M!*(N-M)!}=\cfrac{N!/D}{M!/D * (N-M)!/D} * D^K
C(N,M)=M!∗(N−M)!N!=M!/D∗(N−M)!/DN!/D∗DK
很显然,答案是前面那部分,由于分母不含
D
D
D 因子,分母与
D
D
D 互质,逆元存在,
a
n
s
=
N
!
/
D
∗
i
n
v
(
M
!
/
D
)
∗
i
n
v
(
N
−
M
)
!
/
D
)
m
o
d
D
ans = N!/D * inv(M!/D) * inv(N-M)!/D)~mod~D
ans=N!/D∗inv(M!/D)∗inv(N−M)!/D) mod D
而
n
!
≡
∏
d
∣
i
i
∗
∏
d
∤
i
i
≡
{
d
⌊
n
d
⌋
∗
⌊
n
d
⌋
!
}
∗
{
[
∏
d
∤
i
i
∈
[
1
,
p
]
i
]
⌊
n
p
⌋
∗
∏
d
∤
i
i
∈
[
1
,
n
%
p
]
i
}
(
m
o
d
p
)
n! \equiv \prod\limits_{d\mid i}i * \prod\limits_{d \nmid i}i \equiv \{~d^{\lfloor\frac{n}{d}\rfloor} * \lfloor\cfrac{n}{d}\rfloor!~\} * \{~[~{\prod\limits_{d\nmid i}^{i\in [1,p]} i~]}^{\lfloor\frac{n}{p}\rfloor} * \prod\limits_{d \nmid i}^{i\in[1,n\%p]}i~\} \quad (mod~p)
n!≡d∣i∏i∗d∤i∏i≡{ d⌊dn⌋∗⌊dn⌋! }∗{ [ d∤i∏i∈[1,p]i ]⌊pn⌋∗d∤i∏i∈[1,n%p]i }(mod p)
记
f
(
n
)
=
n
!
/
d
m
o
d
p
,
g
(
n
)
=
∏
d
∤
i
i
∈
[
1
,
n
]
i
m
o
d
p
f(n) = n!/d~mod~p,~g(n) = \prod\limits_{d \nmid i}^{i \in [1,n]} i~mod~p
f(n)=n!/d mod p, g(n)=d∤i∏i∈[1,n]i mod p
有
f
(
n
)
=
f
(
n
/
d
)
∗
g
(
p
)
⌊
n
p
⌋
∗
g
(
n
%
p
)
m
o
d
p
f(n)=f(n/d) * g(p)^{\lfloor\frac{n}{p}\rfloor} * g(n \% p)~mod~p
f(n)=f(n/d)∗g(p)⌊pn⌋∗g(n%p) mod p
O
(
p
)
O(p)
O(p) 预处理出
g
(
n
)
g(n)
g(n),则可以快速求得
f
(
n
)
f(n)
f(n)。
当
D
D
D 不是质数时,分母与
D
D
D 不一定互质,将
D
D
D 唯一分解:
D
=
D
1
∗
D
2
∗
.
.
.
∗
D
s
=
p
1
α
1
∗
p
2
α
2
∗
.
.
.
∗
p
s
α
s
D = D_1 * D_2 * ... * D_s = p_1^{\alpha_1} * p_2^{\alpha_2} * ... * p_s^{\alpha_s}
D=D1∗D2∗...∗Ds=p1α1∗p2α2∗...∗psαs
依然可以求出
C
(
N
,
M
)
=
N
!
M
!
∗
(
N
−
M
)
!
=
N
!
/
p
i
M
!
/
p
i
∗
(
N
−
M
)
!
/
p
i
∗
p
i
k
i
C(N, M) = \cfrac{N!}{M!*(N-M)!}=\cfrac{N!/p_i}{M!/p_i * (N-M)!/p_i} * p_i^{k_i}
C(N,M)=M!∗(N−M)!N!=M!/pi∗(N−M)!/piN!/pi∗piki
进一步可以得到
D
K
D^K
DK 中
K
=
min
i
=
1
s
k
i
α
i
K = \min\limits_{i=1}^{s}\cfrac{k_i}{\alpha_i}
K=i=1minsαiki,
记
C
(
N
,
M
)
=
A
C(N, M) = A
C(N,M)=A,有
a
n
s
≡
A
/
D
≡
A
D
K
≡
A
/
p
i
∗
p
i
k
i
D
K
≡
A
/
p
i
∗
p
i
k
i
−
K
∗
α
i
(
D
D
i
)
K
(
m
o
d
D
i
)
ans \equiv A / D \equiv \cfrac{A}{D^K} \equiv \cfrac{A / p_i * p_i^{k_i}}{D^K} \equiv \cfrac{A/p_i * p_i^{k_i - K * \alpha_i}}{(\frac{D}{D_i})^K} \quad (mod~D_i)
ans≡A/D≡DKA≡DKA/pi∗piki≡(DiD)KA/pi∗piki−K∗αi(mod Di)
此时分母与模数互质,可以求出
a
n
s
%
D
i
ans \% D_i
ans%Di 的结果,再用
c
r
t
crt
crt 求解即可。
参考代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define sz(a) ((int)a.size())
#define pb push_back
#define lson (rt << 1)
#define rson (rt << 1 | 1)
#define gmid (l + r >> 1)
const int maxn = 1e5 + 5;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
ll tp[16000005];
ll m[maxn], a[maxn], pi[maxn], num[maxn], ki[maxn];
ll n, N, M, D, K;
ll qpow(ll a, ll b, ll p){
ll ret = 1;
while(b){
if(b & 1) ret = ret * a % p;
a = a * a % p;
b >>= 1;
}
return ret;
}
void exgcd(ll a, ll b, ll &x, ll &y, ll &d){
if(!b) d = a, x = 1, y = 0;
else exgcd(b, a % b, y, x, d), y -= a / b * x;
}
ll inv(ll a, ll p){
ll x, y, d;
exgcd(a, p, x, y, d);
x = (x % p + p) % p;
return x;
}
ll crt(){
ll M = 1, ret = 0, x, y, d;
for(int i = 1; i <= n; ++i) M *= m[i];
for(int i = 1; i <= n; ++i){
exgcd(M / m[i], m[i], x, y, d);
x = (x % m[i] + m[i]) % m[i];
ret = (ret + M / m[i] * x % M * a[i] % M) % M;
}
return ret;
}
ll cal(ll x, ll p){
ll ret = 0;
while(x){
ret += x / p;
x /= p;
}
return ret;
}
ll cal_fac(ll p){
return cal(N, p) - cal(M, p) - cal(N - M, p);
}
ll dfs(ll n, ll pi, ll p){
if(!n) return 1;
ll ret = qpow(tp[p], n / p, p) * tp[n % p] % p;
return ret * dfs(n / pi, pi, p) % p;
}
ll cal_rem(ll pi, ll p){
tp[0] = 1;
for(ll i = 1; i <= p; ++i){
tp[i] = tp[i - 1];
if(i % pi) tp[i] = tp[i] * i % p;
}
return dfs(N, pi, p) * inv(dfs(M, pi, p), p) % p * inv(dfs(N - M, pi, p), p) % p;
}
void init(){
ll x = D;
for(ll i = 2; i * i <= x; ++i){
if(x % i) continue;
num[++n] = 0, pi[n] = i, m[n] = 1;
while(x % i == 0) ++num[n], x /= i, m[n] *= i;
}
if(x > 1) num[++n] = 1, pi[n] = m[n] = x;
}
int main(){
ios::sync_with_stdio(0); cin.tie(0);
cin >> N >> M >> D;
init();
ki[1] = cal_fac(pi[1]), K = ki[1] / num[1];
for(int i = 2; i <= n; ++i){
ki[i] = cal_fac(pi[i]);
K = min(K, ki[i] / num[i]);
}
for(int i = 1; i <= n; ++i){
a[i] = cal_rem(pi[i], m[i]) * qpow(pi[i], ki[i] - K * num[i], m[i]) % m[i] * qpow(inv(D / m[i], m[i]), K, m[i]) % m[i];
}
ll ret = crt();
cout << ret << endl;
return 0;
}