zoukankan      html  css  js  c++  java
  • BZOJ4559 成绩比较

    题目传送门

    分析:
    我们可以先试着求一下,对于单个学科,有多少种分配方案可以使B神排名为R
    对于第i个学科

    (~~~~g(i)=sum_{j=1}^{H_i}j^{n-R_i}(H_i-j)^{R_i-1})

    相当于枚举B神本人的分数,然后分别将其他人分配
    这个(H_i)很大,但是这个函数是一个大约在n次的多项式,拉格朗日插值一下就好了
    不会?去百度一下,就是套一个公式2333
    然后我们考虑DP
    设f[i][j]表示前i个技能后目前碾压了j个人
    那么

    (~~~~f[i][j]=sum_{k=j}^{n-1}f[i-1][k]C_k^jC_{n-k-1}^{R_i-1-k+j}g(i))

    相当于是在前i-1个技能中碾压的k个人里面选择j个,剩下的n-k-1再选R[i]-1-k+j,一共j个人被碾压
    然后大力DP

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<set>
    
    #define maxn 105
    #define MOD 1000000007
    
    using namespace std;
    
    inline int getint()
    {
    	int num=0,flag=1;char c;
    	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
    	while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
    	return num*flag;
    }
    
    int n,m;
    long long H[maxn],R[maxn];
    long long f[maxn][maxn],g[maxn];
    long long C[maxn][maxn];
    
    inline long long ksm(long long num,long long k)
    {
    	long long ret=1;
    	for(;k;k>>=1,num=num*num%MOD)if(k&1)ret=ret*num%MOD;
    	return ret;
    }
    
    inline long long lagrange(int x)
    {
    	long long ret=0;
    	long long tmp[maxn];memset(tmp,0,sizeof tmp);
    	for(int h=0;h<maxn;h++)for(int i=1;i<=h;i++)
    		(tmp[h]+=ksm(i,n-R[x])*ksm(h-i,R[x]-1))%=MOD;
    	for(int i=0;i<maxn;i++)
    	{
    		long long num=1;
    		for(int j=0;j<maxn;j++)if(i!=j)num=num*(H[x]-j)%MOD*ksm((i-j+MOD)%MOD,MOD-2)%MOD;
    		(ret+=tmp[i]*num)%=MOD;
    	}
    	return (ret+MOD)%MOD;
    }
    
    int main()
    {
    	n=getint(),m=getint();int p=getint();
    	for(int i=1;i<=m;i++)H[i]=getint();
    	for(int i=1;i<=m;i++)R[i]=getint();
    	for(int i=1;i<=m;i++)g[i]=lagrange(i);
    	for(int i=0;i<maxn;i++)
    	{
    		C[i][0]=C[i][i]=1;
    		for(int j=1;j<i;j++)C[i][j]=(C[i-1][j-1]+C[i-1][j])%MOD;
    	}
    	f[0][n-1]=1;
    	for(int i=1;i<=m;i++)for(int j=0;j<n;j++)for(int k=j;k<n;k++)
    		if(R[i]-1-k+j>=0&&n-1-k>=R[i]-1-k+j)
    		(f[i][j]+=f[i-1][k]*C[k][j]%MOD*C[n-k-1][R[i]-1-(k-j)]%MOD*g[i])%=MOD;
    	printf("%lld
    ",f[m][p]);
    }
    

  • 相关阅读:
    javaScript
    CSS
    HTML
    折纸 (模拟)
    不等式(数学)
    周期串查询
    大集训模拟赛十一
    大假期集训模拟赛十
    P1631 序列合并
    KMP(烤馍片)算法
  • 原文地址:https://www.cnblogs.com/Darknesses/p/12243099.html
Copyright © 2011-2022 走看看