bitset入门

来源:互联网 发布:cip数据核字号在哪里 编辑:程序博客网 时间:2024/05/18 13:04

Explosion HDU - 5036
题意:给出n个箱子。每个箱子上都有锁。一把钥匙只能开一把锁,一把锁只有一个钥匙。当然,对于有些没法用钥匙开的箱子,我们必须暴力打开。给出每个箱子中钥匙的数目和具体能开那个箱子,求暴力开箱子的数目的期望,使所有的箱子被打开。

心得:

  1. 期望的可加性。。http://blog.csdn.net/grooowing/article/details/45000205
    感觉忘了挺多,因为这个地方总是以为期望是不可+的。
    参考http://www.cnblogs.com/mengfanrong/p/5186386.html
 思路:每一个房间期望都是可加的。参考单独考虑一个房间,假设有k个房间被炸开都会导致这个房间被打开。那么炸一次这个房间被打开的概率即为kn。也就意味着为了把这个房间打开的期望炸的次数为nk。所有加起来后除以n就可以。bitset优化。
bitset<N>b[N];int  cnt[N];int main(){    int T;sf("%d",&T);    int cas=0;    int n;    while(T--){        sf("%d",&n);        rep(i,0,n-1)b[i].reset(),cnt[i]=0,b[i][i]=1;        rep(i,0,n-1){            int x;sf("%d",&x);            while(x--){                int t;sf("%d",&t);                b[i][t-1]=1;            }        }        mem(cnt,0);        rep(i,0,n-1)            rep(j,0,n-1)                if(b[j][i])                    b[j]|=b[i];        rep(i,0,n-1)            rep(j,0,n-1)                if(b[i][j])cnt[j]++;        double ans=0;        rep(i,0,n-1)ans+=1.0/cnt[i];        pf("Case #%d: %.5lf\n",++cas,ans);    }}

—————————————————————————————————————
参考http://blog.csdn.net/sin_xf/article/details/47080125
题意:给n个点m条边,问最多可以添加几条边使图为完全二分图

分析:如果二分图没有限制,看到是两边分别为n/2个点和n-n/2个点的最优但是可 能出现大于此点的情况,比如n=4,m=3,边为1 2,1 3,1 4.此时完全二分图边最多为3,所以要求得二分图左边或者右边可达到的离n/2最近的点数是多少为最优解,于是采用染色分别求出各个联通快的2种颜色的各个点数,然后用推出能达到的点数,这里dp[i]的下一个状态是dp[i+1]+d[i+1][0]和dp[i+1][1](dp[i]为前i个二分图的能达到的最大点数
),直接做n*n的复杂度,于是采用bitset优化,复杂度降为n,然后在结果中选取最优

感悟:
这个地方的bitset对于dp 的优化很大。。。

int n,m;int e,fst[N],nxt[N<<1],vv[N<<1];int col[N];bitset<10010>dp;void add(int u,int v){    nxt[e]=fst[u];vv[e]=v;fst[u]=e++;}int a1,a2;void dfs(int u,int val){    col[u]=1;    if(val==1)a1++;    else a2++;    for(int i=fst[u];~i;i=nxt[i]){        int v=vv[i];        if(!col[v])dfs(v,val^1);    }}int a[N],b[N];int main(){    int T;sf("%d",&T);    while(T--){        mem(fst,-1);mem(col,0);e=0;        sf("%d%d",&n,&m);        rep(i,1,m){ int u,v;sf("%d%d",&u,&v);add(u,v);add(v,u); }        int cnt=0;        for(int i=1;i<=n;++i){            if(!col[i]){                ++cnt;a1=0,a2=0;                dfs(i,1);                a[cnt]=a1;b[cnt]=a2;                //bug            }        }        dp.reset(); dp[0]=1;        for(int i=1;i<=cnt;++i){            dp=(dp<<a[i])|(dp<<b[i]);        }        int ans=0;        for(int i=1;i<n;++i){            if(dp[i])ans=max(ans,i*(n-i)-m);        }        pf("%d\n",ans);    }}
题目大意:给定两个n阶矩阵,求矩阵相乘后模3.解题思路:因为矩阵模掉3后只有012三种情况。所以对于矩阵A,记录每一行中12的位置,借助bitset。矩阵B中每一列12的位置。然后对于结果中每个位置,只要考虑11,12,2122的个数即可。

感悟:
这个地方的&用的很好。。。
参考http://blog.csdn.net/keshuai19940722/article/details/38391913

int n;bitset<N>x[N][2],y[N][2];int solve(int xx,int yy){    int ret=0;    for(int i=0;i<2;++i){        for(int j=0;j<2;++j){            bitset<N>k;k=x[xx][i]&y[yy][j];            ret=(ret+(i+1)*(j+1)*k.count())%3;        }    }    return ret;}int main(){    while(~sf("%d",&n)){        for(int i=0;i<n;++i){            for(int j=0;j<2;++j)            x[i][j].reset(),y[i][j].reset();        }        for(int i=0;i<n;++i){            for(int j=0;j<n;++j){                int a;sf("%d",&a);a%=3;                if(a)x[i][a-1].set(j,1);            }        }        for(int i=0;i<n;++i){            for(int j=0;j<n;++j){                int a;sf("%d",&a);a%=3;                if(a)y[j][a-1].set(i,1);            }        }        for(int i=0;i<n;++i){            for(int j=0;j<n;++j){                pf("%d%c",solve(i,j),j==n-1?'\n':' ');            }        }    }}

参考http://blog.csdn.net/stay_accept/article/details/71167905

题意:给出n个集合(n<=1000),每个集合中最多有10000个数,每个数的范围为1~10000,给出q次询问(q<=200000),每次给出两个数u,v判断是否有一个集合中同时含有u,v两个数 

分析:一开始觉得10的8次方刚刚好。。。看了题解才知道不需要这样。。

int n;bitset<1010>bi[N];int main(){    while(~sf("%d",&n)){        rep(i,1,10000)bi[i].reset();        rep(i,1,n){            int x;sf("%d",&x);            while(x--){                int u;sf("%d",&u);                bi[u].set(i-1,1);            }        }        int q;sf("%d",&q);        while(q--){            int u,v;sf("%d%d",&u,&v);            bitset<1010>k;k=bi[u]&bi[v];            if(k.count()!=0)puts("Yes");            else puts("No");        }    }}
原创粉丝点击