STL : bitset

之前一直不知道bitset具体的原理,只知道一部分用法。

今天考了一道bitset优化的题,就抽了一些时间研究了一下bitset。

1.原理

就是二进制压位。

具体的可以看一下那道题:

在美丽的比特镇一共有n 个景区,编号依次为1 到n,它们之间通过若干条双向道路连接。

Byteasar 慕名来到了比特镇旅游,不过由于昂贵的门票费,他只能负担起4 个景区的门票费。

他可以在任意景区开始游览,然后结束在任意景区。

Byteasar 的旅游习惯比较特殊,一旦他路过了一个景区,他就一定会进去参观,并且他永远不会参观同一个景区两次。

所以他想知道,有多少种可行的旅游路线,使得他可以恰好参观4 个景区呢?即,有多少条简单路径恰好经过了4 个点。

Input

第一行包含两个整数n,表示景区的总数。

第2 至第n + 1 行,每行一个长度为n 的01 字符串,第i + 1 行第j 个字符为0 表示i 和j 之间没有道路,为1 表示有一条道路。

输入数据保证(i; j) 的连接情况等于(j; i) 的连接情况,且(i; i) 恒为0。

Output

输出一行一个整数,即可行的路线总数。

Examples

tour.in

4

0101

1010

0101

1010

tour.out

 8

8 条路线分别为:

1->2->3->4,4->3->2->1,

2->3->4->1,1->4->3->2,

3->4->1->2,2->1->4->3,

4->1->2->3,3->2->1->4。

Notes

测试点编号     n

     1              = 5

     2              = 10

     3              = 20

     4              = 50

     5              = 300

     6              = 300

     7              = 300

     8              = 1500

     9              = 1500

     10            = 1500

标程在这里(标程手写bitset,太巨了%%%):

 1 #include<cstdio>
 2 const int N=1510;
 3 int cnt[65536],m,n,i,j,d[N];char g[N][N];long long ans;
 4 int popcount(unsigned int x){return cnt[x>>16]+cnt[x&65535];}
 5 struct BIT{
 6   unsigned int v[47];
 7   void set(int x){v[x>>5]|=1U<<(x&31);}
 8   void count(const BIT&b){for(int i=0;i<=m;i++)ans-=popcount(v[i]&b.v[i]);}
 9 }f[N];
10 int main(){
11   freopen("tour.in","r",stdin);freopen("tour.out","w",stdout);
12   for(i=1;i<65536;i++)cnt[i]=cnt[i>>1]+(i&1);
13   scanf("%d",&n);m=(n-1)>>5;
14   for(i=0;i<n;i++){
15     scanf("%s",g[i]);
16     for(j=0;j<n;j++)if(g[i][j]=='1')f[i].set(j),d[i]++;
17   }
18   for(i=0;i<n;i++)for(j=0;j<i;j++)if(g[i][j]=='1')ans+=(d[i]-1)*(d[j]-1),f[i].count(f[j]);
19   printf("%I64d",ans*2);
20   fclose(stdin);fclose(stdout);
21   return 0;
22 }
标程

2.使用方法

定义:

bitset<666>x;    //定义一个包含666位的bitset叫做x 
bitset<666>x(0xfa2);    //赋初值 
bitset<666>x(string("0101111001"));    //另一种赋初值 

常用函数:

x.size();    //返回x的位数 
x.set();    //将x的所有位设为1
x.set(k);    //将x的第k位设为1
x.set(k,a);    //将第k位设为a 
x.reset();    //将x的所有位设为0
x.reset(k);    //将x的第k位设为0
x.any();    //如果x中存在某一位是1,返回true;否则返回false
x.none();    //如果x中所有位都是0,返回true;否则返回false
x.count();    //返回x中1的个数
x.test();    //返回x的第k位的值
x.flip();    //翻转x的所有位的值(0变成1,1变成0)
x.flip(k);    //翻转x的第k位的值
x.to_ulong()    //返回它转换为unsigned long的结果,如果超出范围则报错
x.to_ullong()    //返回它转换为unsigned long long的结果,如果超出范围则报错
x.to_string()    //返回它转换为string的结果

另外我们也可以用下标来访问、修改bitset中的位。

int res=x[3];
x[5]=1;

注意下标从0开始。

运算:

bitset的运算类似整数。

可以用==、!=、~、<<、>>、&、|、^、<<=、>>=、&=、|=、^=等运算符。

3.时间&空间&应用

可以在<bitset>头文件看出,bitset使用unsigned long进行压位的。

也就是说空间和时间都能被bitset压缩至1/32。

所以我们可以用bitset实现邻接矩阵等只含有0或1的数据结构,这样可以优化时间和空间。

posted @ 2018-10-26 15:06  cervusky  阅读(345)  评论(0编辑  收藏  举报

Contact with me