[luogu P3270] [JLOI2016]成绩比较
先不考虑分数
首先设
N
=
n
−
k
−
1
N = n - k - 1
N=n−k−1,表示B神没能碾压的人
这个显然是
C
n
−
1
N
C_{n-1}^{N}
Cn−1N
对于第
i
i
i科,排在B神前面的肯定在N里面
C
N
r
a
n
k
[
i
]
−
1
\large C_{N}^{rank[i]-1}
CNrank[i]−1
把
m
m
m个科目的答案乘起来
F
(
m
)
=
∏
i
=
1
m
C
N
r
a
n
k
[
i
]
−
1
\large F(m)=\prod\limits_{i=1}^{m} C_{N}^{rank[i]-1}
F(m)=i=1∏mCNrank[i]−1
显然这个会把一些不合法的算进去
怎么办?
容斥就好了
a
n
s
=
∑
i
=
0
N
(
−
1
)
N
−
i
C
N
i
F
(
i
)
\large ans=\sum\limits_{i=0}^{N} (-1)^{N-i} \ C_{N}^{i}F(i)
ans=i=0∑N(−1)N−i CNiF(i)
a
n
s
=
∑
i
=
0
N
(
−
1
)
N
−
i
C
N
i
∏
j
=
1
m
C
i
r
a
n
k
[
j
]
−
1
\large ans=\sum\limits_{i=0}^{N} (-1)^{N-i} \ C_{N}^{i}\prod\limits_{j=1}^{m} C_{i}^{rank[j]-1}
ans=i=0∑N(−1)N−i CNij=1∏mCirank[j]−1
这个计算是
O
(
n
m
)
O(nm)
O(nm)的
加上分数怎么搞呢?
枚举B神的分数
S
i
=
∑
x
=
1
U
i
x
n
−
r
a
n
k
[
i
]
(
U
i
−
x
)
r
a
n
k
[
i
]
−
1
\large S_i=\sum\limits_{x=1}^{U_i}x^{n-rank[i]}(U_i-x)^{rank[i]-1}
Si=x=1∑Uixn−rank[i](Ui−x)rank[i]−1
二项式展开
(
U
i
−
x
)
r
a
n
k
[
i
]
−
1
=
∑
t
=
0
r
a
n
k
[
i
]
−
1
(
−
1
)
t
C
r
a
n
k
[
i
]
−
1
t
x
t
U
i
r
a
n
k
[
i
]
−
1
−
t
(U_i-x)^{rank[i]-1}=\sum\limits_{t=0}^{rank[i]-1} (-1)^tC_{rank[i]-1}^{t}x^tU_i^{rank[i]-1-t}
(Ui−x)rank[i]−1=t=0∑rank[i]−1(−1)tCrank[i]−1txtUirank[i]−1−t
( U i − x ) r a n k [ i ] − 1 = ∑ t = 0 r a n k [ i ] − 1 ( − 1 ) t x t U i r a n k [ i ] − 1 − t C r a n k [ i ] − 1 t (U_i-x)^{rank[i]-1}=\sum\limits_{t=0}^{rank[i]-1} (-1)^tx^tU_i^{rank[i]-1-t}C_{rank[i]-1}^{t} (Ui−x)rank[i]−1=t=0∑rank[i]−1(−1)txtUirank[i]−1−tCrank[i]−1t
S
i
=
∑
x
=
1
U
i
x
n
−
r
a
n
k
[
i
]
∑
t
=
0
r
a
n
k
[
i
]
−
1
(
−
1
)
t
x
t
U
i
r
a
n
k
[
i
]
−
1
−
t
C
r
a
n
k
[
i
]
−
1
t
\large S_i=\sum\limits_{x=1}^{U_i}x^{n-rank[i]}\sum\limits_{t=0}^{rank[i]-1} (-1)^tx^tU_i^{rank[i]-1-t}C_{rank[i]-1}^{t}
Si=x=1∑Uixn−rank[i]t=0∑rank[i]−1(−1)txtUirank[i]−1−tCrank[i]−1t
S
i
=
∑
x
=
1
U
i
∑
t
=
0
r
a
n
k
[
i
]
−
1
(
−
1
)
t
x
n
−
r
a
n
k
[
i
]
+
t
U
i
r
a
n
k
[
i
]
−
1
−
t
C
r
a
n
k
[
i
]
−
1
t
\large S_i=\sum\limits_{x=1}^{U_i}\sum\limits_{t=0}^{rank[i]-1} (-1)^tx^{n-rank[i]+t}U_i^{rank[i]-1-t}C_{rank[i]-1}^{t}
Si=x=1∑Uit=0∑rank[i]−1(−1)txn−rank[i]+tUirank[i]−1−tCrank[i]−1t
交换求和顺序
S
i
=
∑
t
=
0
r
a
n
k
[
i
]
−
1
(
−
1
)
t
U
i
r
a
n
k
[
i
]
−
1
−
t
C
r
a
n
k
[
i
]
−
1
t
∑
x
=
1
U
i
x
n
−
r
a
n
k
[
i
]
+
t
\large S_i=\sum\limits_{t=0}^{rank[i]-1} (-1)^tU_i^{rank[i]-1-t}C_{rank[i]-1}^{t}\sum\limits_{x=1}^{U_i}x^{n-rank[i]+t}
Si=t=0∑rank[i]−1(−1)tUirank[i]−1−tCrank[i]−1tx=1∑Uixn−rank[i]+t
A
N
S
=
C
n
−
1
N
∗
a
n
s
∗
∏
i
=
1
m
S
i
\large ANS = C_{n-1}^{N}*ans*\prod\limits_{i=1}^{m}S_i
ANS=Cn−1N∗ans∗i=1∏mSi
然后就可以了
∏
i
=
1
m
S
i
\prod\limits_{i=1}^{m}S_i
i=1∏mSi计算这个东西是
O
(
m
n
2
)
O(mn^2)
O(mn2)的,这就是上限
让我们来看看展开后的毒瘤式子吧
A
N
S
=
C
n
−
1
N
∗
∑
i
=
0
N
(
−
1
)
N
−
i
C
N
i
∏
j
=
1
m
C
i
r
a
n
k
[
j
]
−
1
∗
∏
k
=
1
m
∑
t
=
0
r
a
n
k
[
k
]
−
1
(
−
1
)
t
U
k
r
a
n
k
[
k
]
−
1
−
t
C
r
a
n
k
[
k
]
−
1
t
∑
x
=
1
U
k
x
n
−
r
a
n
k
[
k
]
+
t
ANS = C_{n-1}^{N}*\sum\limits_{i=0}^{N} (-1)^{N-i} \ C_{N}^{i}\prod\limits_{j=1}^{m} C_{i}^{rank[j]-1}*\prod\limits_{k=1}^{m}\sum\limits_{t=0}^{rank[k]-1} (-1)^tU_k^{rank[k]-1-t}C_{rank[k]-1}^{t}\sum\limits_{x=1}^{U_k}x^{n-rank[k]+t}
ANS=Cn−1N∗i=0∑N(−1)N−i CNij=1∏mCirank[j]−1∗k=1∏mt=0∑rank[k]−1(−1)tUkrank[k]−1−tCrank[k]−1tx=1∑Ukxn−rank[k]+t
还是看这条吧
A
N
S
=
C
n
−
1
N
∗
a
n
s
∗
∏
i
=
1
m
S
i
\large ANS = C_{n-1}^{N}*ans*\prod\limits_{i=1}^{m}S_i
ANS=Cn−1N∗ans∗i=1∏mSi
直接rush就好了
忘记讲了
∑
x
=
1
U
i
x
n
−
r
a
n
k
[
i
]
+
t
\sum\limits_{x=1}^{U_i}x^{n-rank[i]+t}
x=1∑Uixn−rank[i]+t这个是多项式幂和,可以用拉格朗日插值法
O
(
n
)
O(n)
O(n)求出
code:
#include<bits/stdc++.h>
#define N 1000005
#define int long long
#define mod 1000000007
using namespace std;
int qpow(int x, int y) {
int ret = 1;
for(; y; y >>= 1, x = x * x % mod) if(y & 1) ret = ret * x % mod;
return ret;
}
int Fac[N], iFac[N], S[N], U[N], R[N];
int C(int x, int y) {
if(x < y) return 0;
return Fac[x] * iFac[y] % mod * iFac[x - y] % mod;
}
int n, m, k, x[N], y[N], fac[N], pre[N], suf[N];
int nk(int n, int k) {
swap(n, k);
n += 2;
for(int i = 1; i <= n; i ++) {
x[i] = i;
y[i] = (y[i - 1] + qpow(i, n - 2)) % mod;
}
fac[0] = pre[0] = suf[n + 1] = 1;
int s = 1;
for(int i = 1; i <= n; i ++) fac[i] = fac[i - 1] * i % mod, pre[i] = pre[i - 1] * (k - x[i] + mod)% mod;
for(int i = n; i >= 1; i --) suf[i] = suf[i + 1] * (k - x[i] + mod) % mod;
int ans = 0;
for(int i = 1; i <= n; i ++) {
int pi = pre[x[i] - 1] * suf[x[i] + 1] % mod;
int ha = fac[x[i] - 1] * fac[n - x[i]] % mod;
if((n - i) & 1) ha = (mod - ha) % mod;
pi = pi * qpow(ha, mod - 2) % mod;
ans = (ans + y[i] * pi % mod) % mod;
}
return ans;
}
signed main() {
scanf("%lld%lld%lld", &n, &m, &k);
int nn = n - k - 1;
for(int i = 1; i <= m; i ++) scanf("%lld", &U[i]);
for(int i = 1; i <= m; i ++) scanf("%lld", &R[i]);
Fac[0] = 1;
for(int i = 1; i <= n; i ++) Fac[i] = Fac[i - 1] * i % mod;
iFac[n] = qpow(Fac[n], mod - 2);
for(int i = n - 1; i >= 0; i --) iFac[i] = iFac[i + 1] * (i + 1) % mod;
int ANS = C(n - 1, nn);
int ans = 0;
for(int i = 0; i <= nn; i ++) {
int ret = 1;
for(int j = 1; j <= m; j ++) ret = ret * C(i, R[j] - 1) % mod;
ret = ret * C(nn, i) % mod;
if((nn - i) & 1) ans = (ans - ret + mod) % mod;
else ans = (ans + ret) % mod;
}
for(int i = 1; i <= m; i ++) {
for(int t = 0; t <= R[i] - 1; t ++) {
int ret = qpow(U[i], R[i] - 1 - t);
ret = ret * C(R[i] - 1, t) % mod;
ret = ret * nk(U[i], n - R[i] + t) % mod;
if(t & 1) S[i] = (S[i] - ret + mod) % mod;
else S[i] = (S[i] + ret) % mod;
}
}
ANS = ANS * ans % mod;
for(int i = 1; i <= m; i ++) ANS = ANS * S[i] % mod;
printf("%lld", ANS);
return 0;
}
这条式子我推了半个小时
哈哈哈哈哈哈我没疯,放开我哈哈哈,哈那塞哈哈哈哈