洛谷P2104·模拟二进制

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷P2104·模拟二进制相关的知识,希望对你有一定的参考价值。

题面

题目描述

小Z最近学会了二进制数,他觉得太小的二进制数太没意思,于是他想对一个巨大二进制数做以下 4 种基础运算:

运算 1:将整个二进制数加 1

运算 2:将整个二进制数减 1

运算 3:将整个二进制数乘 2

运算 4:将整个二进制数整除 2

小Z很想知道运算后的结果,他只好向你求助。

(Ps:为了简化问题,数据保证+,-操作不会导致最高位的进位与退位)

输入输出格式

输入格式:

第一行两个正整数 n,m,表示原二进制数的长度以及运算数。

接下来一行 n 个字符,分别为‘0’或‘1’表示这个二进制数。

第三行 m 个字符,分别为‘+’,‘-’,‘*’,‘/’,对应运算 1,2,3,4。

输出格式:

一行若干个字符,表示经过运算后的二进制数。

输入输出样例

输入样例#1:

4 10
1101
*/-*-*-/*/

 

输出样例#1:

10110

说明

【数据规模和约定】

对于 30%的数据,1 ≤ n,m ≤ 1000。

对于 60%的数据,1 ≤ n,m ≤ 10^5。

对于 100%的数据,1 ≤ n,m ≤ 5*10^6。

【时空限制】

2s/128M

分析

首先看一下数据,n和m最多可以到5000000。

这说明什么呢,就是我们要用些比较玄学的做法了...

我们知道,n/2=n>>1,n*2=n<<1。

那我们的乘除运算就可以再优化一点了。

然而,如果直接右移或左移一位的话,效率就是O(n),太慢...

于是我想出了一个比较好的方法,就是栈模拟(?)...

右移一位,相当于把最低位去掉,也就是出栈(pop);

左移一位,相当于末尾加一个0,也就是入栈(push)一个0。

这样一来,我们就能把乘除运算优化到O(1)了。

加法的话,我们可以一直从最低位往最高位访问,不停地改变,如果是0就跳出循环。

例如n=1101011,加法运算后是n=1101100,我们只要访问到百位就可以了。

减法同理。

这样一来,加法和减法的最差效率是O(n),乘除的最差效率是O(1),应该没问题。

提交了也AC了。

程序

#include <cstdio>
using namespace std;
bool bin[10000005];
int end=-1;
int main(){
    int i, j;
    int n, m;
    char ch;
    
    scanf("%d %d ", &n, &m);
    for(i=1; i<=n; i++){
        end++;
        bin[end]=getchar()&1;
    }
    scanf(" ");
    for(i=1; i<=m; i++){
        ch=getchar();
        if(ch==+){
            j=end;
            while(bin[j]){
                bin[j]=0;
                j--;
            }
            bin[j]=1;
        }
        else if(ch==-){
            j=end;
            while(!bin[j]){
                bin[j]=1;
                j--;
            }
            bin[j]=0;
        }
        else if(ch==*) end++;
        else{
            bin[end]=0;
            end--;
        }
    }
    for(i=0; i<=end; i++)
        putchar(bin[i]+48);
    return 0;
}

 

以上是关于洛谷P2104·模拟二进制的主要内容,如果未能解决你的问题,请参考以下文章

洛谷 P2104 二进制

洛谷·NOIP模拟测试一·2017/10/2考后心得与检讨

洛谷P1095·贪心·动态规划守望者的逃离

洛谷P2784·图论·Spfa化学1(chem1)- 化学合成

洛谷P2858·动态规划[USACO06FEB]奶牛零食Treats for the Cows

[二〇二一八月 · 洛谷月赛 · PMOI-4]题解汇总(口胡)