[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∏m​CNrank[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 CNi​F(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 CNi​j=1∏m​Cirank[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∑Ui​​xn−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]−1t​xtUirank[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−t​Crank[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∑Ui​​xn−rank[i]t=0∑rank[i]−1​(−1)txtUirank[i]−1−t​Crank[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∑Ui​​t=0∑rank[i]−1​(−1)txn−rank[i]+tUirank[i]−1−t​Crank[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−t​Crank[i]−1t​x=1∑Ui​​xn−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∏m​Si​
然后就可以了
∏ i = 1 m S i \prod\limits_{i=1}^{m}S_i i=1∏m​Si​计算这个东西是 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 CNi​j=1∏m​Cirank[j]−1​∗k=1∏m​t=0∑rank[k]−1​(−1)tUkrank[k]−1−t​Crank[k]−1t​x=1∑Uk​​xn−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∏m​Si​
直接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∑Ui​​xn−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;
}

这条式子我推了半个小时
哈哈哈哈哈哈我没疯,放开我哈哈哈,哈那塞哈哈哈哈

posted @ 2020-09-18 18:43  lahlah  阅读(35)  评论(0)    收藏  举报