UVALive - 6886 Golf Bot (bitset)

题目链接:

UVA-6886

题目大意:

n n 个数 A[1,,n] A [ 1 , … , n ] m m 个数 B[1,,m] B [ 1 , … , m ] ;问在 A A 中选 1 1 个或 2 2 个数,能构成 (指相加) 多少个 B B 中的数?

数据范围:

1n,m2e51Ai,Bi2e5 1 ≤ n , m ≤ 2 e 5 1 ≤ A i , B i ≤ 2 e 5

解题思路:

DP的复杂度不够,只想到一个比较好的暴力,送上一发TLE;后经 cp 大佬强力优化,终于在T,W之后看到了AC!
赛后发现大佬用 bitset 做的,嗯,,,bitset,了解一下?

定义:

主要有三种构造方式:

bitset <16> A;
bitset <16> B (0xfa2);    //十六进制构造
bitset <16> C (string("011001"));    //字符串构造

//A: 0000000000000000
//B: 0000111110100010
//C: 0000000000011001
基本运算:

什么与(&),或(|),非(~),异或(^),左移(<<),右移(>>) 都是有的!等于(==),不等于(!=)也都是有的。
C++ bitset 内部实现是非常 nice 的!很快!

基本函数:

bt.count() //1 的个数
bt.any() //返回是否有1
bt.none() //返回是否没有1
bt.set() //全部置为1
bt.reset() //全部置为0
bt.set(p) //把 p 位置为1
bt.reset(p) //把 p 位置为 0
bt.set(p, x) //把 p 位置为 x (x为0 或 1)
bt.flip() //全部取反
bt.flip(p) //把 p 位取反
bt.to_string() //转为 string


回到题目上来;只要把选 1 1 个数 和 选 2 2 个数能构成的状态处理出来,跟 B B 数组的状态与 (&) 一下,统计 1 1 的个数就可以了。

AC代码:

/**********************************************
 *Author*        :XzzF
 *Created Time*  : 2018/5/24 16:14:29
 *Ended  Time*  : 2018/5/24 16:23:52
*********************************************/

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long LL;
const int inf = 1 << 30;
const LL INF = 1LL << 60;
const int MaxN = 200000;

int n, m;
int a[MaxN + 5];
bitset  A, B, ans;

int main()
{
    while(scanf("%d", &n) != EOF)
    {
        for(int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            A.set(a[i]);
        }
        scanf("%d", &m);
        for(int i = 1; i <= m; i++) {
            int x;
            scanf("%d", &x);
            B.set(x);
        }
        ans |= (B & A);    //只选1个数
        for(int i = 1; i <= n; i++)    //选2个数
            ans |= (B & (A << a[i]));
        printf("%d\n", ans.count());
        A.reset(); B.reset(); ans.reset();
    }
    return 0;
}



强行打一波广告:压位卡常题必备神器,bitset,值得拥有!

你可能感兴趣的:(STL)