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);
}
好吧的确挺♂妙
先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);
}
相关文章推荐
- ActiveMQ的简单使用
- 【日记】学习Android开发
- Using 1-Wire device with Intel Galileo
- 计算KS值的标准代码
- Mongodb 在update时 org.springframework.data.mapping.context.InvalidPersistentPropertyPath: No property
- POJ 1741 树分治
- Shell并发编程Demo
- 愚蠢的错误 Failed to connect to 127.0.0.1 port 8888 :conection refused
- 2017年1月数据结构实训总结
- Android开发 WebView TextToSpeech异常
- jxl 导出excel springMVC
- 【SSH网上商城项目实战08】查询和删除商品类别功能的实现
- 平常开发总结
- Java四种线程池的使用
- activemq官方文档分析
- POJ 1741 树分治
- csan博客 I am coming
- Netty做http服务端例程
- AngularJs
- FunDA(3)- 流动数据行操作:FDAPipeLine operations using scalaz-stream-fs2