bzoj4559JLOI2016成绩比较
Posted AaronPolaris
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj4559JLOI2016成绩比较相关的知识,希望对你有一定的参考价值。
4559: [JLoi2016]成绩比较
Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 37 Solved: 29
[Submit][Status][Discuss]
Description
Input
Output
仅一行一个正整数,表示满足条件的情况数模10^9+7的余数。
Sample Input
2 2
1 2
Sample Output
容斥原理+组合数,思路好
wangyuzee的题解很棒,orz
整体思路:先求出所有其他人和B神每门课分数相对大小的不同方案数,然后再计算每门课的方案数,两者乘积即为答案。
① 先算第一部分,直接算比较难,考虑容斥原理。
f[i]表示有i个人被碾压的方案数,则f[i]=C(n-1,i)*C(n-1-i,rnk[1]-1)*C(n-1-i,rnk[2]-1)*…*C(n-1-i,rnk[m]-1)-f[i+1]*C(i+1,i)-f[i+2]*C(i+2,i)-…-f[n-1]*C(n-1,i),即用至少i个人被碾压的方案数减去不合法的。f数组逆向递推即可求出。
② 再算第二部分,对于每一门分别计算,然后乘起来。
假设某一门课的总分为s,B神的名次和分数分别为rnk和x,则方案数为x^(n-rnk)*(s-x)^(rnk-1)。
展开化简得∑ C(rnk-1,i)*s^(rnk-1-i)*x^(n-rnk+i),0≤i≤rnk-1。
我们要对x=1,2,…,s的所有情况求和。
把x次数相同的项放在一起,转化成求1^p+2^p+...+s^p,p为常数。
设g[i]=1^i+2^i+...+s^i,然后观察规律:
(s+1)^(p+1)-s^(p+1)=C(p+1,0)*s^0+C(p+1,1)*s^1+…+C(p+1,p)*s^p
s^(p+1)-(s-1)^(p+1)=C(p+1,0)*(s-1)^0+C(p+1,1)*(s-1)^1+…+C(p+1,p)*(s-1)^p
……
2^(p+1)-1^(p+1)=C(p+1,0)*1^0+C(p+1,1)*1^1+…+C(p+1,p)*1^p
将式子相加,得:(s+1)^(p+1)-1=C(p+1,0)*g[0]+C(p+1,1)*g[1]+…+C(p+1,p)*g[p]
移项,得:g[p]=((s+1)^(p+1)-1-C(p+1,0)*g[0]-C(p+1,1)*g[1]-…-C(p+1,p-1)*g[p-1]) / C(p+1,p)
于是可以通过正向递推求出g数组。
这样,这个问题就完美解决了,时间复杂度O(n^3)。
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #include<algorithm> #define F(i,j,n) for(int i=j;i<=n;i++) #define D(i,j,n) for(int i=j;i>=n;i--) #define ll long long #define N 105 #define mod 1000000007 using namespace std; int n,m,k; ll ans,s[N],rnk[N],fac[N],inv[N],f[N],g[N]; inline int read() { int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } inline ll getpow(ll x,ll y) { ll ret=1; for(;y;y>>=1,x=x*x%mod) if (y&1) ret=ret*x%mod; return ret; } inline ll C(int x,int y) { return fac[x]*inv[y]%mod*inv[x-y]%mod; } int main() { n=read();m=read();k=read(); F(i,1,m) s[i]=read(); F(i,1,m) rnk[i]=read(); fac[0]=inv[0]=1; F(i,1,100) fac[i]=fac[i-1]*i%mod,inv[i]=getpow(fac[i],mod-2); D(i,n-1,k) { f[i]=C(n-1,i); F(j,1,m) f[i]=f[i]*C(n-1-i,rnk[j]-1)%mod; F(j,i+1,n-1) f[i]=(f[i]-f[j]*C(j,i)%mod+mod)%mod; } ans=1; F(i,1,m) { g[0]=s[i]; F(j,1,n) { g[j]=(getpow(s[i]+1,j+1)-1+mod)%mod; F(l,0,j-1) g[j]=(g[j]-C(j+1,l)*g[l]%mod+mod)%mod; g[j]=g[j]*getpow(j+1,mod-2)%mod; } ll tmp=0,p=1; F(j,0,rnk[i]-1) tmp=(tmp+C(rnk[i]-1,j)*getpow(s[i],rnk[i]-1-j)%mod*g[n-rnk[i]+j]%mod*p+mod)%mod,p=-p; ans=ans*tmp%mod; } cout<<ans*f[k]%mod<<endl; return 0; }
以上是关于bzoj4559JLOI2016成绩比较的主要内容,如果未能解决你的问题,请参考以下文章
bzoj 4559 [JLoi2016]成绩比较 —— DP+拉格朗日插值
BZOJ4559[JLoi2016]成绩比较 动态规划+容斥+组合数学
bzoj千题计划270:bzoj4559: [JLoi2016]成绩比较