E简单瞎搞题(bitset)

简单瞎搞题

https://ac.nowcoder.com/acm/problem/17193

这个题目还有点意思。。。一开始愣是没看懂。。。暴力的做法O(100^100)超时,因为最终要是求得所有不同数的个数,我们考虑用二进制表示这个数能出现或者不能出现。二进制操作有一个非常好用的工具是bitset。如果不会bitset,http://www.cplusplus.com/reference/bitset/bitset/。因为数字最大无非是,,所以bitset开到1e6就行了,bitset从右边往左边走,它的位置表示十进制位置。感觉说不太清,直接举例子吧。
如果输入
2
1 2
1 2
先考虑,我们有,
看一下二进制是如何操作的。
图片说明
给定表示二进制串向左移动个位置,这个位置刚好就是i所对应的十进制数,一开始设,表示答案串最后一位为1没有实际意义就是为了后面的操作。然后,这个时候字符串下标1的位置字符串0变1(|有1则1),然后,这个时候字符串4的位置0变1,看到这里应该明白了,01二进制串第表示这个数不会出现,为表示这个数出现,并且下标就是对应这个数的值。我们再来考虑,看它是怎么累加的。结束后我们要保存这个结果串,然后继续遍历,这个时候,s1已经是上一个区间数的串了,在这个基础上继续左移,,当
图片说明
注意到,表示的就是(对应下标看)。然后还有,就是最后一个串,因为我们只要求出现一次的数,出现多次的会被运算覆盖掉,然后不断迭代,最后答案串的的个数就是的种类数。
代码:

#include<iostream>
#include<bitset> 
using namespace std;

const int maxn = 1100000 ;
void solved(){
    int n;cin>>n;
    bitset<maxn>s1,s2;
    s1.set(0);
    while(n--){
        s2.reset(); 
        int l,r;cin>>l>>r;
        for(int i = l ; i <= r; i++){
            s2 |= s1 << (i * i);
        }
        s1 = s2;
    }
    cout<<(int)s1.count()<<endl;
}
int main(){
    solved();
    return 0;
}
全部评论
大佬您的字串貌似是反的,起点应该是右边吧,不然左移不就越界了吗?
点赞 回复 分享
发布于 2021-06-30 21:28

相关推荐

叶扰云倾:进度更新,现在阿里云面完3面了,感觉3面答得还行,基本都答上了,自己熟悉的地方也说的比较细致,但感觉面试官有点心不在焉不知道是不是不想要我了,求阿里收留,我直接秒到岗当阿里孝子,学校那边的房子都退租了,下学期都不回学校,全职猛猛实习半年。这种条件还不诱人吗难道 然后现在约到了字节的一面和淘天的复活赛,外加猿辅导。华为笔试完没动静。 美团那边之前投了个base广州的,把我流程卡麻了,应该是不怎么招人,我直接简历挂了,现在进了一个正常的后端流程,还在筛选,不知道还有没有hc。
点赞 评论 收藏
分享
评论
5
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务