您的位置:首页 > 其它

BZOJ 4559: [JLoi2016]成绩比较【计数dp,容斥,组合数

2017-01-12 18:00 316 查看
听说王队长的题解特别妙【摔

好吧的确挺♂妙

先yy出求每个人相对排名不同的方案数(用f来记录)

因为是有顺序的……所以不能直接容斥……就用 f[i] 表示 有刚好 i 个人被碾压的方案数 , 再用 至少 i 个人被碾压的方案数 减掉不合法的

看代码吧,还是挺好懂的,或者前两篇题解也写的很稳【王队长的题解啊exciting

然后求在每种排名下 分数不同的方案数……自己yy一下 C一C……xjb搞就完啦【真的不是忙着回家懒得码字了【滑稽

嘤……jq爸爸的容斥这么强于是Flaze莫名入了计数dp的坑,虽然因为太弱被jq 裱上了天2333

哼 我觉得jq马上就能上传说233333

代码↓

#include<bits/stdc++.h>
#define MAXN 105
#define MOD 1000000007ll
using namespace std; int n,m,K;
inline int read() {
register int ch = getchar();
while(!isdigit(ch)) ch = getchar();
register int rtn = 0;
while(isdigit(ch)) rtn = rtn*10 + ch - '0' , ch = getchar();
return rtn;
}

inline long long pow_(long long d,int c) {
long long rtn = 1 ;
for(;c;c>>=1,d = d*d%MOD)
if(c&1)
(rtn *= d) %= MOD;
return rtn ;
}

long long u[MAXN] , rk[MAXN] , max_rank = 0 ;
long long fac[MAXN] , inv[MAXN];

long long f[MAXN] , g[MAXN];

inline long long C(int a,int b) {return fac[a]*inv[b] %MOD *inv[a-b] %MOD;}
inline long long A(int a,int b) {return fac[a]*inv[a-b] %MOD;}

int main() {
//freopen("1.in","r",stdin);
n = read() , m = read() , K = read();
for (int i=1;i<=m;++i) u[i] = (long long) read();
for (int i=1;i<=m;++i)
max_rank = max( max_rank , rk[i] = (long long) read() );

//printf("max = %lld\n",max_rank);
if(K> n - max_rank) return puts("0"),0;

fac[0] = 1 , inv[0] = 1;
for (int i=1;i<=100;++i)
fac[i] = fac[i-1] * i % MOD , inv[i] = pow_(fac[i],MOD-2);

for(int i=n-max_rank;i;--i){
f[i] = C(n-1,i);
for(int j=1;j<=m;++j) ( f[i] *= C(n-i-1,rk[j]-1) ) %= MOD;
for(int j=n-max_rank;j^i;--j)
( f[i] += MOD - C(j,i)*f[j]%MOD ) %= MOD;
}

//printf("%lld\n",f[K]);

long long tmp = 1;
for(int i=1;i<=m;++i){
memset(g,0,sizeof g);
g[0] = u[i];
long long bbb = u[i] + 1 ;
long long base = bbb * bbb % MOD;
for(int k=1;k<=n;++k) {
g[k] = base - 1 ;
long long mns = 0;
for(int j=0;j<k;++j)
(mns += C(k+1,j)*g[j]%MOD) %= MOD;
(g[k] += MOD - mns ) %= MOD;
(g[k] *= pow_(k+1,MOD-2) ) %= MOD;
base *= bbb;
base %= MOD;
}

bbb = 0;
for(int j=0;j<rk[i];++j){
if(j&1)
(bbb += MOD
- C(rk[i]-1,j) * pow_(u[i],rk[i]-1-j) % MOD * g[n-rk[i]+j] % MOD) %= MOD;
else (bbb += C(rk[i]-1,j) * pow_(u[i],rk[i]-1-j) % MOD * g[n-rk[i]+j]) %= MOD;
}
(tmp *= bbb) %= MOD;

//printf("bbb = %lld\n",bbb);
}

printf("%lld\n",tmp * f[K] % MOD);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: