「JLOI / SHOI2016」成绩比较

「JLOI / SHOI2016」成绩比较

传送门

Loj

题解

首先考虑可以分成两个部分计算,即人数和分数.

1. 人数的计算:

很明显可以容斥,设\(f_{i}\)表示至少吊打\(i\)个人,那么有:

\[\begin{align} f_{i}&=\binom{n-1}{i}\prod_{j=1}^m\binom{r_j-1}{n-i-1} \\ ans&=\sum_{i=k}^nf_i\binom{i}{k}-1^{i-k} \end{align} \]

此时容斥系数不为\(\pm 1\).

2. 分数的计算:

考虑单独计算一科的分数,为:

\[\begin{align} ans_i&=\sum_{j=1}^{u_i}j^{n-r_i}{(u_i-j)}^{r_i-1} \\ &=\sum_{j=1}^{u_i}j^{n-r_i}\sum_{k=0}^{r_i-1}-1^ku_i^{r_i-1-k}j^{k}\binom{r_i-1}{k} \\ &=\sum_{j=1}^{u_i}\sum_{k=0}^{r_i-1}-1^ku_i^{r_i-1-k}j^{n-r_i+k}\binom{r_i-1}{k} \\ &=\sum_{k=0}^{r_i-1}-1^k\binom{r_i-1}{k}u_i^{r_i-1-k}\sum_{j=1}^{u_i}j^{n-r_i+k} \end{align} \]

前面的直接枚举,后面的自然数幂和用第二类斯特林数算即可.

\[\sum_{i=1}^ni^k=\sum_{j=0}^k\begin{Bmatrix}k\\j\end{Bmatrix}\frac{(n+1)^{\underline {j+1}}}{j+1} \]

代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<iostream>
using namespace std;
#define ll long long
#define REP(a,b,c) for(int a=b;a<=c;a++)
#define re register
#define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
typedef pair<int,int> pii;
#define mp make_pair
inline int gi()
{
	int f=1,sum=0;char ch=getchar();
	while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
	return f*sum;
}
const int N=210,Mod=1e9+7;
int n,m,k,u[N],r[N];
int c[N][N],S[N][N];
int qpow(int a,int b){int ret=1;while(b){if(b&1)ret=1ll*ret*a%Mod;b>>=1;a=1ll*a*a%Mod;}return ret;}
int calc(int n,int k)
{
	int down=1,ret=0;
	for(int j=0;j<=k;j++)
	{
		down=1ll*down*(n+1-j)%Mod;
		ret=(ret+1ll*down*S[k][j]%Mod*qpow(j+1,Mod-2)%Mod)%Mod;
	}
	return ret;
}
int main()
{
	n=gi();m=gi();k=gi();
	c[0][0]=1;
	for(int i=1;i<=200;i++)
	{
		c[i][0]=1;
		for(int j=1;j<=i;j++)c[i][j]=(c[i-1][j]+c[i-1][j-1])%Mod;
	}
	S[0][0]=1;
	for(int i=1;i<=200;i++)
	{
		for(int j=1;j<=200;j++)
			S[i][j]=(S[i-1][j-1]+1ll*j*S[i-1][j]%Mod)%Mod;
	}
	for(int i=1;i<=m;i++)u[i]=gi();
	for(int i=1;i<=m;i++)r[i]=gi();
	int ans=0;
	for(int i=0,f=(n-k-1)&1?Mod-1:1;i<=n-k-1;i++,f=Mod-f)
	{
		int res=1ll*f*c[n-k-1][i]%Mod;
		for(int j=1;j<=m;j++)res=1ll*res*c[i][r[j]-1]%Mod;
		ans=(ans+res)%Mod;
	}
	ans=1ll*ans*c[n-1][k]%Mod;
	for(int i=1;i<=m;i++)
	{
		int res=0;
		for(int p=0,f=(r[i]-1)&1?Mod-1:1;p<r[i];p++,f=Mod-f)
			res=(res+1ll*f*c[r[i]-1][p]%Mod*qpow(u[i],p)%Mod*calc(u[i],n-p-1)%Mod)%Mod;
		ans=1ll*ans*res%Mod;
	}
	printf("%d\n",ans);
	return 0;
}
posted @ 2020-05-11 14:13  fexuile  阅读(162)  评论(0编辑  收藏  举报