Luogu P1795 无穷的序列+bitset的福利

题目大意

有一个无穷序列如下:

110100100010000100000……

请你找出这个无穷序列中指定位置上的数字。

分析

观察1的位置就会发现有规律。1的位置为:1 2 4 7 11……
所以1的位置可以记录下来。

但是我还是有N次没A!我真%我自己


一堆代码

代码1(70分,纯粹暴力)

不TLE就怪了

#include<iostream>
using namespace std;
int i,m,n,j,k;
int a[1500000];
bool f(int a){
    for(j=m=1;m<a;j++)m+=j;
    return m==a;
}
int main(){
    cin>>n;
    for(i=1;i<=n;i++){
        cin>>k;
        cout<<f(k)<<endl;
    }
    return 0;
}    

代码2(MLE爆0)

#include<iostream>
using namespace std;
int i,m,n,j,k;
int a[1500000];
int s[100000001]; //当初我并不知道数组不能开这么大Orz
bool f(int a){
    if(a<=100000000 && s[a]!=2)return s[a];
    for(j=m=1;m<a;j++)m+=j;
    if(a<=100000000)return s[a]=(m==a);
    return m==a;
}
int main(){
    cin>>n;
    for(i=1;i<=100000000;i++)s[i]=2; 
    for(i=1;i<=n;i++){
        cin>>k;
        cout<<f(k)<<endl;
    }
    return 0;
}   

代码3(70分RE)

其实正式比赛会爆0

#include<bits/stdc++.h>
using namespace std;
long long maxx,i,m,n,j,k;
long long f[10000001],a[1500001]; //又是超大的数组
int main(){
    f[1]=1;m=1;
    scanf("%lld",&n);
    for(i=1;i<=n;i++){
        scanf("%lld",a+i);
        maxx=max(a[i],maxx);
    }
    m=f[1]=1;
    for(i=2;m<=maxx;i++){
        f[i]=f[i-1]+m;
        m++;
    }
    for(i=1;i<=n;i++){
        j=1;
        while(f[j]<a[i])j++;
        printf("%d\n",f[j]==a[i]);
    }
    return 0;
}

代码4(90分没错就是map)

#include<bits/stdc++.h>
using namespace std;
int maxx,i,m,n,j,k;
int a[1500001]; 
int main(){
    map<int,int>p;
    scanf("%d",&n);
    for(i=1;i<=n;i++){
        scanf("%d",a+i);
        maxx=max(a[i],maxx);
    }
    for(i=1;i<=maxx;i+=m){
        p[i]=1;
        m++;
    }
    for(i=1;i<=n;i++)
        printf("%d\n",(p[a[i]]==1));
    return 0;
}

然而TLE了~~
上期我简单介绍了一下map,今天我要补充一下,map比较慢(原来以为不会TLE的)

代码5(AC bitset)

Wow,用bitset存储0-1的信息真的超爽也。

#include<bits/stdc++.h>
using namespace std;
int maxx,i,m,n,j,k;
int a[1500001]; 
bitset<100000000>p;//默认都是0
int main(){
    scanf("%d",&n);
    for(i=1;i<=n;i++){
        scanf("%d",a+i);
        if(a[i]>maxx)maxx=a[i];
    }
    for(i=1;i<=maxx;m++,i+=m)
        p.set(i);//将i处设置为1
    for(i=1;i<=n;i++)
        printf("%d\n",p.test(a[i]));//看看a[i]是0是1
    return 0;
}

我来解释一下bitset
bitset≈bit+set(众:什么鬼)
bitset的原理是用二进制的位来存储(其实也是1个STL,跟map一样)。用他来存储0-1的情况比用bool省内存多了。那么为什么呢?因为1个字节是8位,一个bool是一字节,自己去换算吧。

附加:bitset的一些用法(福利来了)

定义:

bitset<n>a;         //a有n位,皆为0
bitset<n>a(x);      //a为unsigned long形x的一个二进制副本
bitset<n>a(s);      //a是string对象s中含有的位串的副本
bitset<n>a(s,pos,n);//b是s中从位置pos开始的n个位的副本

操作:

操作解释
b.any()b中是否存在置为1的二进制位?
b.none()b中不存在置为1的二进制位吗?
b.count()b中置为1的二进制位的个数
b.size()b中二进制位的个数
b[pos]访问b中在pos处的二进制位
b.test(pos)b中在pos处的二进制位是否为1?
b.set()把b中所有二进制位都置为1
b.set(pos)把b中在pos处的二进制位置为1
b.reset()把b中所有二进制位都置为0
b.reset(pos)把b中在pos处的二进制位置为0
b.flip()把b中所有二进制位逐位取反
b.flip(pos)把b中在pos处的二进制位取反
b.to_ulong()用b中同样的二进制位返回一个unsigned long值
os << b把b中的位集输出到os流

福利就到这里,祖师爷我去也~~

总结

好吧,这道“水题”的总结还是得写写

  1. 数组不要开大了
  2. map查找数据较慢,不要乱用
  3. 试试用bitset
  4. 暴力出奇迹,但暴力效率低

就先到这里吧

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值