Turtle and an Infinite Sequence

# Turtle and an Infinite Sequence

<a href="https://codeforces.com/contest/1981/problem/B">原题链接</a>

这道题是一道位运算的题,比较容易,但要实现比较复杂,对初学位运算的同学来讲比较有挑战性

## 原题

There is a sequence a0,a1,a2,… of infinite length. Initially ai=i for every non-negative integer i.

After every second, each element of the sequence will imultaneously change. ai will change to ai−1∣ai∣ai+1 for every positive integer i. a0 will change to a0∣a1. Here, | denotes bitwise OR.

Turtle is asked to find the value of an after m seconds. In particular, if m=0, then he needs to find the initial value of an. He is tired of calculating so many values, so please help him!

## Input

Each test contains multiple test cases. The first line ontains the number of test cases t (1≤t≤104). The escription of the test cases follows.

The first line of each test case contains two integers n,m (0≤n,m≤109).


 

## Output

For each test case, output a single integer — the value of an after m seconds.

## Example

### Input

```

9

0 0

0 1

0 2

1 0

5 2

10 1

20 3

1145 14

19198 10

```

### Output

```

0

1

3

1

7

11

23

1279

19455

```

### Note

After 1 second, [a0,a1,a2,a3,a4,a5] will become [1,3,3,7,7,7].

After 2 seconds, [a0,a1,a2,a3,a4,a5] will become [3,3,7,7,7,7].

## 思路

朴素的暴力(从n - m 到n + m遍历或运算)会超时,那么我们自然想到了要通过对每一位进行处理来得出答案

解决本题要按位处理,对每一位是零还是一做判断即可

```

#include <bits/stdc++.h>

using namespace std;

// 该函数用于截取取从第l位到第r位的二进制数的十进制形式

int getnum(vector<int> n, int l, int r)

{

    int res = 0;

    for(int i = l; i >= r; i -- )

    {

        res = res * 2 + n[i];

    }

   

    return res;

}


 

void solve()

{

    int n, m;

    cin >> n >> m;

   

    int temp = n;

   

    vector<int> num;

    // 这里用于将n这个十进制数用二进制数组存起来

    // 存储顺序是从0到num.size()从二进制的低位到高位

    while(n)

    {

        num.push_back(n % 2);

        n /= 2;

    }

   

    // 处理一下n + m的情况,因为如果n + m的最高位高于n的最高位,则从n + m的最高位到最低位一定全是1

    n = temp + m;

   

    vector<int> num2;

   

    while(n)

    {

        num2.push_back(n % 2);

        n /= 2;

    }

   

    // 特判刚刚所说的情况

    if(num2.size() > num.size())

    {

        int res = 0;

        for(int i = num2.size() - 1; i >= 0; i -- )

        {

            res *= 2;

            res += 1;

        }

        cout << res << endl;

       

        return;

    }

   

   

    n = num.size();

   

    int res = 0;

    // 从最高位到最低位逐个检查是1是0,处理res为最终答案

    for(int i = n - 1; i >= 0; i -- )

    {

        res *= 2;

        // 最高位的1一定存在啊

        if(i == n - 1)

        {

            res += 1;

            continue;

        }

       

        // 如果当前位是1就res + 1

        if(num[i] == 1)

        {

            res += 1;

            continue;

        }

       

        // k是n的第i位以下的数的十进制形式

        int k = getnum(num, i - 1, 0);

        // k1是二进制第i位的十进制形式

        int k1 = 1 << i;

        // 如果可以通过加法加到第i位的1

        if(m >= k1 - k)

        {

            res += 1;

            continue;

        }

        // 如果通过减法减到第i位的1也可以

        if(m >= k + 1)

        {

            res += 1;

            continue;

        }

    }

   

    cout << res << endl;

   

    return;

}

int main()

{

    int t;

    cin >> t;

    while(t -- )

    {

        solve();

    }

   

    return 0;

}

```

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值