[JZOJ]兔兔和蛋蛋
来源:互联网 发布:怎样挑选淘宝供应商 编辑:程序博客网 时间:2024/04/28 11:04
题目大意
以1为根的树有n个点,每个点i有个贡献值为a[i],还可以分配一个b[i],其中
现在问贡献值为0~K的分配方案分别有多少,模1e9+7。
注:开O2
分析
首先40分直接
分析一下m从14跨越到1e8怎么做?那我们肯定只用知道我们的方案的b[i]的种类数,然后组合数就可以了嘛。
n=14,也不可折半,那么应该是个状压DP。直接按DFN做?没用啊。
很机智地,我们从小到大填b[i]。这里的b[i]是离散后的。
那么设f[i][j][s]为,填到i,当前贡献为j,n个点的填数与否状态为s,的方案数。
考虑转移,直接暴力枚举填i+1的点有哪些相当于枚举子集,这样是
那么这时考虑按dfn来做,发现每次只需要填一个数,不管是填i+1还是填i,都没有影响。这样就得出了新的算法:s的状态顺序为dfn,转移的话,对于一个f[i][j][s],我们可以填i,即同层转移,也可以填i+1,转移到新的一层。这样子时间复杂度是
我打的时候想复杂了,常数巨大,枚举了许多无用状态,当然复杂度还是一样的嘛····
代码
#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>using namespace std;#define fo(i,j,k) for(i=j;i<=k;i++)#define fd(i,j,k) for(i=j;i>=k;i--)typedef long long ll;typedef double db;const int N=17000;const int mo=1e9+7;int lim,i,j,k,l,s,ans,kx,n,m,K,ct;int cnt[N],av[N][25],And[25][25],a[25];int f[17][22][N],g[17][22][N],rev[25],fac[25];int tt,b[25],next[25],first[25],dfn[25],ref[25],siz[25],t1;void cr(int x,int y){ tt++; b[tt]=y; next[tt]=first[x]; first[x]=tt;}void dfs(int x){ dfn[x]=++t1; siz[x]=1; ref[t1]=x; for(int p=first[x];p;p=next[p]) { dfs(b[p]); siz[x]+=siz[b[p]]; }}int ksm(int x,int y){ int ret=1; while (y) { if (y&1) ret=1ll*ret*x%mo; y>>=1; x=1ll*x*x%mo; } return ret;}void predo(){ fo(i,0,lim) fo(j,0,n-1) if (i&(1<<j)) cnt[i]++; else av[i][++av[i][0]]=j+1; fo(i,0,n-1) fo(j,i,n-1) And[i][j]=And[i][j-1]+(1<<j); fac[0]=1; fo(i,1,n) fac[i]=1ll*fac[i-1]*i%mo; fo(i,0,n) rev[i]=ksm(fac[i],mo-2);}void trans(int i){ int j,k,l,s,x,tmp; fo(j,0,K) fo(s,0,lim) if (f[i][j][s]) { fo(k,1,av[s][0]) { ct++; x=av[s][k]; tmp=a[ref[x]]*cnt[And[x-1][x+siz[ref[x]]-1-1]&s]; if (j+tmp<=K) (g[x][j+tmp][s+(1<<(x-1))]+=f[i][j][s])%=mo; } } fo(k,1,n) fo(j,0,K) fo(s,0,lim) if (g[k][j][s]) { for(l=1;l<=av[s][0]&&av[s][l]<=k;l++); fo(l,l,av[s][0]) { ct++; x=av[s][l]; tmp=a[ref[x]]*cnt[And[x-1][x+siz[ref[x]]-1-1]&s]; if (j+tmp<=K) (g[x][j+tmp][s+(1<<(x-1))]+=g[k][j][s])%=mo; } }}int c(int n,int m){ int ret=1,l; fd(l,m,m-n+1) ret=1ll*ret*l%mo; return 1ll*ret*rev[n]%mo;}int main(){ scanf("%d %d %d\n",&n,&m,&K); m++; fo(i,1,n) scanf("%d",a+i); fo(i,2,n) { scanf("%d",&j); cr(j,i); } dfs(1); f[0][0][0]=1; lim=(1<<n)-1; predo(); fo(i,0,min(n,m)-1) { trans(i); fo(k,1,n) fo(j,0,K) fo(s,0,lim) { f[i+1][j][s]=(f[i+1][j][s]+g[k][j][s])%mo; g[k][j][s]=0; } } fo(k,0,K) { ans=0; fo(i,1,min(n,m)) { kx=c(i,m); ans=(1ll*ans+1ll*kx*f[i][k][lim])%mo; } printf("%d\n",ans); }}
0 0
- [JZOJ]兔兔和蛋蛋
- NOI 兔兔与蛋蛋的游戏
- bzoj2437 [Noi2011]兔兔与蛋蛋
- BZOJ2437: [Noi2011]兔兔与蛋蛋
- ★【二分图匹配】【博弈论】【NOI2011】兔兔和蛋蛋的游戏
- bzoj 2437 [Noi2011]兔兔与蛋蛋 [二分图匹配]
- 【bzoj2437】【NOI2011】【兔兔与蛋蛋】【二分图博弈】
- 【博弈+二分图匹配】[NOI2011]兔兔与蛋蛋游戏
- [BZOJ]2437 [NOI2011] 兔兔与蛋蛋 二分图博弈
- bzoj2437: [Noi2011]兔兔与蛋蛋 二分图博弈
- [BZOJ 2437][NOI 2011]兔兔与蛋蛋(二分图匹配)
- 【BZOJ2437】【codevs1949】兔兔与蛋蛋游戏,博弈+二分图匹配
- [二分图博弈] BZOJ 1443 [JSOI2009]游戏Game & BZOJ 2437 [Noi2011]兔兔与蛋蛋
- bzoj 2437: [Noi2011]兔兔与蛋蛋 (二分图博弈+dinic)
- 【NOI2011T6】兔兔与蛋蛋的游戏-二分图最大匹配+博弈
- [BZOJ]2437: [Noi2011]兔兔与蛋蛋 二分图匹配+博弈
- BZOJ 2437 兔兔与蛋蛋 (博弈论 二分图匹配)
- 蛋蛋阅读
- Linux 关机重启命令
- ssh框架中,Struts2中返回默认值input,根本action都不执行
- php 连接操作mysql数据库
- Linux DM9000网卡驱动程序完全分析
- Jenkins进阶系列之——17Jenkins升级、迁移和备份
- [JZOJ]兔兔和蛋蛋
- nyoj 325 zb的生日
- 个人千峰前端10天学习
- 非递归前序中序后序遍历二叉树
- java jni 数据转换
- 制作在线升级工具-Ramdisk文件系统的制作与调试运行
- 运用springmvc实现文件上传下载
- python使用xlwt模块操作Excel
- Factory模式