51nod 1446
来源:互联网 发布:ai cc for mac破解版 编辑:程序博客网 时间:2024/06/03 20:35
一个good点如果只和bad相连就不计算他的价值,否则算入总价值记作great点,要求总价值<=maxval
这些good点之间除了权值没啥区别,生成树计数容易想到用矩阵树定理去统计,但是用矩阵树定理,只能通过让他们之和bad间有边限制i个点一定不是great点,对于其他点有可能还有不是great点的情况统计
于是用g[i]表示至少i个good点非great,f[i]表示恰好i个good点非great,用减掉恰好j(j>i)个good点非great的情况,考虑我们固定了1~i非great,共m个good点,剩下j-i个非great点在m-i个里面有
值非常大不能dp,所以统计sum<=maxval的great情况貌似NPC?
要2^n枚举,直接枚举不能接受,考虑折半,枚举哪些点是great,i个great点的情况枚举出来后排序,然后meet in middle
复杂度
code:
#include<set>#include<map>#include<deque>#include<queue>#include<stack>#include<cmath>#include<ctime>#include<bitset>#include<string>#include<vector>#include<cstdio>#include<cstdlib>#include<cstring>#include<climits>#include<complex>#include<iostream>#include<algorithm>#define ll long longusing namespace std;const int maxn = 42;const int Mod = 1e9+7;inline void add(int &x,const int &y){x+=y;if(x>=Mod)x-=Mod;}inline void dec(int &x,const int &y){x-=y;if(x<0)x+=Mod;}int pw(int x,int k){ if(x<0) x+=Mod; int re=1; for(;k;k>>=1,x=(ll)x*x%Mod) if(k&1) re=(ll)re*x%Mod; return re;}int inv(int x){return pw(x,Mod-2);}int n,m,N,val;int c[maxn][maxn],v[maxn];struct matrix{int a[maxn];}a[maxn];void Gauss(){ for(int i=1;i<N;i++) { if(a[i].a[i]==0) { int flag=-1; for(int j=i+1;j<N;j++) if(a[j].a[i]) { flag=j;break; } if(flag!=-1) for(int j=1;j<N;j++) swap(a[i].a[j],a[flag].a[j]); } if(a[i].a[i]==0) return; int cc=inv(a[i].a[i]); for(int j=i+1;j<N;j++) if(a[j].a[i]) { int div=(ll)cc*a[j].a[i]%Mod; for(int k=i;k<N;k++) dec(a[j].a[k],(ll)a[i].a[k]*div%Mod); } }}int g[maxn],f[maxn];void cal(const int k){ for(int i=1;i<=N;i++) memset(a[i].a,0,sizeof a[i].a); for(int i=1;i<=k;i++) { for(int j=1;j<=n;j++) { int id=m+j; a[i].a[i]++,a[id].a[id]++; a[i].a[id]--,a[id].a[i]--; } } for(int i=k+1;i<N;i++) { for(int j=i+1;j<=N;j++) { a[i].a[i]++,a[j].a[j]++; a[i].a[j]--,a[j].a[i]--; } } for(int i=1;i<=N;i++) for(int j=1;j<=N;j++) dec(a[i].a[j],0); Gauss(); g[k]=1; for(int i=1;i<N;i++) g[k]=(ll)g[k]*a[i].a[i]%Mod;}vector<int>V1[maxn],V2[maxn];void search(){ int mid=N>>1; int al=1<<mid; for(int i=0;i<=mid;i++) V1[i].clear(); for(int i=0;i<al;i++) { int num=0,sum=0; for(int j=1;j<=mid;j++) if(i>>j-1&1) { if(v[j]==-1) { num=-1; break; } num++,sum+=v[j]; } if(num!=-1) V1[num].push_back(sum); } for(int i=0;i<=mid;i++) sort(V1[i].begin(),V1[i].end()); al=1<<N-mid; for(int i=0;i<=N-mid;i++) V2[i].clear(); for(int i=0;i<al;i++) { int num=0,sum=0; for(int j=1;j<=N-mid;j++) if(i>>j-1&1) { if(v[mid+j]==-1) { num=-1; break; } num++,sum+=v[mid+j]; } if(num!=-1) V2[num].push_back(sum); } for(int i=0;i<=N-mid;i++) sort(V2[i].begin(),V2[i].end());}struct node{int i,j,x;};inline bool operator <(const node x,const node y){return x.x<y.x;}priority_queue<node>q;int match[maxn];int main(){ c[0][0]=1; for(int i=1;i<maxn;i++) { c[i][0]=1; for(int j=1;j<maxn;j++) c[i][j]=(c[i-1][j-1]+c[i-1][j])%Mod; } int tcase; scanf("%d",&tcase); while(tcase--) { scanf("%d%d",&n,&val); for(int i=1;i<=n;i++) scanf("%d",&v[i]); N=n; m=0; for(int i=1;i<=n;i++) if(v[i]!=-1) m++; n=N-m; for(int i=0;i<=m;i++) cal(i); for(int i=m;i>=0;i--) { f[i]=g[i]; for(int j=i+1;j<=m;j++) dec(f[i],(ll)f[j]*c[m-i][j-i]%Mod); } search(); int mid=N>>1; int re=0; for(int i=0;i<=mid;i++) { memset(match,0,sizeof match); while(!q.empty()) q.pop(); for(int j=0;j<=N-mid;j++) if(V2[j].size()) q.push((node){j,V2[j].size()-1,V2[j][V2[j].size()-1]}),match[j]=V2[j].size(); for(int j=0;j<V1[i].size();j++) { int cc=V1[i][j]; if(q.empty()) break; while(!q.empty()) { node now=q.top(); if(cc+now.x<=val) break; q.pop(); for(;now.j>=0&&V2[now.i][now.j]+cc>val;now.j--) match[now.i]--; if(now.j<0) continue; now.x=V2[now.i][now.j]; q.push(now); } for(int l=0;l<=N-mid;l++) if(match[l]) add(re,(ll)match[l]*f[m-(i+l)]%Mod); } } printf("%d\n",re); } return 0;}
阅读全文
0 0
- 51nod 1446
- 51Nod
- 51Nod
- 51nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 统一建模语言(UML)
- 指针和数组
- acm的常见返回结果
- Qt学习笔记
- 11.20学习心得
- 51nod 1446
- mysql 连接url中useUnicode=true&characterEncoding=UTF-8 的作用
- servlet05-ajax
- SpringMVC拦截器
- C++_图形界面、Qt 简单的使用、Hello world
- 总结(一)基于统计学的点云去噪
- 常量表达式
- Fidder Script
- (转)一个经典例子让你彻彻底底理解java回调机制