题解 P3270 【[JLOI2016]成绩比较】
WinXP
2018-06-08 14:03:28
开始的时候这么多量我是一头雾水,所以只好一点点求。
//所涉及到的变量如未特殊声明即为题目中的变量
.
1.首先根据题意同学们是互不相同的。(显然...)
$k$ 名同学被B神碾压。$k$ 名同学的组成共有 $C^k_{n-1}$ 种方式。
2.嗯..然后 $n-k-1$ (记为 $num$ ) 名同学是没有被B神碾压的,所以每人都至少有一科比B神高。
3.再然后,B神排名是已知的,所以考虑比B神某科高的人出现在 $num$ 名同学中的方案。显然为 $C^{Rk-1}_{num}$。
4.把 $m$ 科一起算,计 $T_{num}$ 为m个科目分给 $num$ 人的方案数,为
$$T_{num}=\prod_{k=1}^{m} {C^{R_k-1}_{num}}$$
5.不过有个问题,$num$ 人不被B神碾压,要求每个人都至少有一科比B神高,这样计算会出现只涉及到一部分人的情况。
容斥一下。得
$$T=\sum_{i=0}^{num}(-1)^{num-i} C_{num}^i T_{i}$$
$$=\sum_{i=0}^{num}(-1)^{num-i} C_{num}^i\prod_{k=1}^{m} {C^{R_k-1}_{i}}$$
那么到现在 $C^{k}_{n-1}T$ 即为同学比B神的成绩相对大小的方案数。不过还没有考虑分数的问题。
6.先考虑单科,考虑某一科满足B神排名为 $Ri$ 的方案数。
7.首先,$n$ 个同学分布在 $x$ 分内的方案显然为 $x^n$ (最低为1分,开始我没好好读题以为可以有0分卡了好久),因为我们只是考虑同学与B神的分数高低方案,同学间的高低没算在内,所以不是组合数形式...
因为 $Ri-1$ 名同学必须严格大于B神,$n-Ri$ 名同学是小于等于B神,所以不能简单乘一乘,那就枚举b神的分数
$$Si=\sum_{x=1}^{Ui} x^{n-Ri}(Ui-x)^{Ri-1}$$
这显然会T,因为 $Ui$ 很大。
8.所以~~根据经验~~就乱搞一下———把后面的$(Ui-x)^{Ri-1}$展开~~应该会很不错~~。然后交换一下求和的顺序。
$$Si=\sum_{x=1}^{Ui} x^{n-Ri}(Ui-x)^{Ri-1}$$
$$=\sum_{x=1}^{Ui} x^{n-Ri} \sum_{t=0}^{Ri-1}(-1)^t C^t_{Ri-1}Ui^{Ri-1-t}x^t$$
$$=\sum_{x=1}^{Ui} \sum_{t=0}^{Ri-1}(-1)^t C^t_{Ri-1}Ui^{Ri-1-t}x^t x^{n-Ri}$$
$$= \sum_{t=0}^{Ri-1}(-1)^t C^t_{Ri-1}Ui^{Ri-1-t}\sum_{x=1}^{Ui}x^{n-Ri+t}$$
那么这个东西就可求了。求出 $\sum_{x=1}^{Ui}x^{n-Ri+t}$就可以了。
怎么就可求了呢?
9.考虑$1^2+2^2+3^2+4^2+...+n^2=\frac{n(n+1)(2n+1)}{6}$的证明方法。其中一种证明法为:
设$Tn=(n+1)^3-n^3$,有
$$Tn=(n+1)^3-n^3=3n^2+3n+1$$
然后显然的是
$$\sum_{i=1}^n Ti=(n+1)^3-n^3+n^3-(n-1)^3+...-1^3$$
$$=(n+1)^3-1$$
根据上面还有
$$\sum_{i=1}^n Ti=3 \sum_{i=1}^n i^2+3\sum_{i=1}^ni+\sum_{i=1}^n1$$
10.所以对于 $1^t+2^t+3^t+...+n^t$ 可以用类似方法求。把这个数列记为 $X_t^n$,则有
$$(n+1)^{t+1}-1=\sum_{i=0}^t C_{t+1}^{t-i+1} X_i^n$$
$$X_t^n=(n+1)^{t+1}-1-\sum_{i=0}^{t-1} C_{t+1}^{t-i+1}X_i^n$$
$$X_0^n=n$$
可以在$O(t^2)$时间内得到 $X$。
11.认真考虑一下,好像没有别的了。当然乘一起。
$$ans=C^k_{n-1}T\prod_{i=1}^m Si$$
$$=C^k_{n-1}(\sum_{i=0}^{num}(-1)^{num-i}C_{num}^i \prod_{k=1}^{m} {C^{R_k-1}_{i}})\prod_{i=1}^m \sum_{t=0}^{Ri-1}(-1)^t C^t_{Ri-1}Ui^{Ri-1-t}X_{n-Ri+t}^{Ui}$$
复杂度$O(mn^2)$,主要在于处理 $X$ 。
```cpp
#include <bits/stdc++.h>
#define rap(i,s,n) for(int i=s;i<=n;i++)
#define drap(i,s,n) for(int i=s;i>=n;i--)
#define N 233
#define ll long long
#define P 1000000007
#define m(s,k) memset(s,k,sizeof s)
using namespace std;
char xB[1<<15],*xS=xB,*xTT=xB;
#define getc() (xS==xTT&&(xTT=(xS=xB)+fread(xB,1,1<<15,stdin),xS==xTT)?0:*xS++)
#define isd(c) ((c>='0'&&c<='9')||(c=='-'))
template<typename T>
inline bool rd(T& xa){
char xchh; T f=1; while(xchh=getc(),(!isd(xchh))&&(xchh!=0));
if(xchh==0) return 0; if(xchh=='-') xchh=getc(),f=-1; xa=xchh-'0';
while(xchh=getc(),isd(xchh)) xa=xa*10+xchh-'0'; xa*=f; return 1;
}
ll mpow(ll a,ll k,ll p){ll res=1; while(k){if(k&1) res=res*a%p; k>>=1; a=a*a%p;} return res%p;}
int n,m,nm,num,k,R[N];
ll U[N],C[N][N],X[N][N],inv[N];
int main(){
rd(n),rd(m),rd(k); rap(i,1,m) rd(U[i]); rap(i,1,m) rd(R[i]); num=n-k-1,nm=max(n,m);
C[0][0]=1; rap(i,1,nm+10){C[i][0]=1; rap(j,1,i) C[i][j]=(C[i-1][j-1]+C[i-1][j])%P;}
inv[1]=1; rap(i,2,n+10) inv[i]=inv[P%i]*(P-P/i)%P;
ll T=0,f=-1; drap(i,num,0){f=-f; ll Ti=1; rap(k,1,m) Ti=(Ti*C[i][R[k]-1])%P; T=(T+Ti*f*C[num][i]+P)%P;}
rap(k,1,m) rap(t,0,n){
ll s=0; rap(i,0,t-1) s=(s+C[t+1][t-i+1]*X[k][i])%P;
X[k][t]=(mpow(U[k]+1,t+1,P)-1-s+P)%P*inv[t+1]%P;
}
ll S=1; rap(i,1,m){
ll si=0,f=-1;
rap(t,0,R[i]-1) f=-f,si=(si+f*C[R[i]-1][t]*mpow(U[i],R[i]-1-t,P)%P*X[i][n-R[i]+t]%P+P)%P;
S=(S*si+P)%P;
}
printf("%lld\n",C[n-1][k]*T%P*S%P);
return 0;
}
```