bzoj4559: [JLoi2016]成績比較

感謝丁爺爺教我作這個題的後半部分。ios

首先,運用一發容斥原理,求出全部人與B神每門課分數相對關係的不一樣方案數。ui

這個彷佛大(wo)家(lan)都(de)會(hui)了(yi),我就不說了,詳見代碼裏的f。spa

而後,咱們就須要計算每門課每一個人的分數的方案數。對於每一門課,咱們分別計算,而後把它們乘起來。blog

方便起見,令總分爲s,名次爲rk。get

設B神的分數爲x,則方案數爲x^(n-rk)*(s-x)^(rk-1)string

展開獲得c(rk-1,0)*s^(rk-1)*x^(n-rk)-c(rk-1,1)*s^(rk-2)*x^(n-rk+1)+c(rk-1,2)*s^(rk-3)*x^(n-rk+2)-........it

顯然,咱們須要對於x=1..s的全部狀況求和。io

咱們把x次數相同的項放在一塊兒,進行一波整理,問題就轉化成了求1^k+2^k+...+s^kast

咱們設g(k)=1^k+2^k+...+s^k,咱們列出一波式子而後觀察:class

(s+1)^k-s^k=c(k,1)*s^(k-1)     +c(k,2)*s^(k-2)     +...+c(k,k)*s^0

 s^k-(s-1)^k=c(k,1)*(s-1)^(k-1)+c(k,2)*(s-1)^(k-2)+...+c(k,k)*(s-1)^0

............................................................................................................

      2^k-1^k=c(k,1)*1^(k-1)     +c(k,2)*1^(k-2)     +...+c(k,k)*1^0

把這些式子所有相加,獲得:

(s+1)^k-1=c(k,1)*g(k-1)+c(k,2)*g(k-2)+...+c(k,k)*g(0)

因而就能夠經過遞推的方式求出g

而後就作完了。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#define ll long long
#define N 103
#define P 1000000007

using namespace std;
inline int read(){
	int ret=0;char ch=getchar();
	while (ch<'0'||ch>'9') ch=getchar();
	while ('0'<=ch&&ch<='9'){
		ret=ret*10-48+ch;
		ch=getchar();
	}
	return ret;
}

int fast_pow(int x,int y){
	int ret=1;
	while (y){
		if (y&1) ret=(ll)ret*x%P;
		x=(ll)x*x%P;
		y=y>>1;
	}
	return ret;
}

int bin[N];
int fact[N*100];
int inv[N*100];
int c(int n,int m){
	return (ll)fact[n]*inv[m]%P*inv[n-m]%P;
}

int f[N],g[N];
int person,subject,K;
int rank[N],s[N];
int main(){
	for (int i=fact[0]=1;i<=1e3;++i) fact[i]=(ll)fact[i-1]*i%P;
	for (int i=0;i<=1e3;++i) inv[i]=fast_pow(fact[i],P-2);
	person=read();subject=read();K=read();
	for (int i=1;i<=subject;++i) s[i]=read();
	int maxrank=0;
	for (int i=1;i<=subject;++i) maxrank=max(maxrank,rank[i]=read());
	for (int i=person-maxrank;i>=K;--i){
		f[i]=c(person-1,i);
		for (int j=1;j<=subject;++j)
			f[i]=(ll)f[i]*c(person-1-i,rank[j]-1)%P;
		for (int j=person-maxrank;j>i;--j)
			(f[i]+=P-(ll)f[j]*c(j,i)%P)%=P;
	}
	int res=1;
	for (int i=1;i<=subject;++i){
		g[0]=s[i];
		bin[0]=1;
		for (int j=1;j<=person;++j){
			bin[j]=(ll)bin[j-1]*s[i]%P;
			g[j]=fast_pow(s[i]+1,j+1)-1;
			for (int k=1;k<=j;++k)
				(g[j]+=P-(ll)c(j+1,k+1)*g[j-k]%P)%=P;
			g[j]=(ll)g[j]*fast_pow(c(j+1,1),P-2)%P;
		}
		int now=0;
		for (int j=0,k=1;j<rank[i];++j,k=-k)
			(now+=((ll)k+P)*c(rank[i]-1,j)%P*g[person-rank[i]+j]%P*bin[rank[i]-j-1]%P)%=P;
		res=(ll)res*now%P;
	}
	printf("%lld\n",(ll)res*f[K]%P);
	return 0;
}
相關文章
相關標籤/搜索