OJ打卡练习/3.31

  1. 二进制插入

链接:https://www.nowcoder.com/practice/30c1674ad5694b3f8f0bc2de6f005490?tpId=8&&tqId=1101

描述

给定两个32位整数n和m,同时给定i和j,将m的二进制数位插入到n的二进制的第j到第i位,保证n的第j到第i位均为零,且m的二进制位数小于等于i-j+1,其中二进制的位数从0开始由低到高。

测试样例

1024,19,2,6

返回:1100

i j m:1024:100000000 00

n: 19 :10011 要把n的二进制值插入m的第j位到第i位,只需要把n先左移j位,然 后再进行或运算(|)即可。 m: 10000000000 n: 00001001100 10001001100

class BinInsert {
public:
    int binInsert(int n, int m, int j, int i) {
        //1.将m左移j位
        return (m<<j)|n;
        // write code here
    }
};

这道题主要是位运算的熟练掌握,插入到n且题目保证了j~i范围内n的二进制位为0所以直接m移位后再按位或就好啦

  1. 查找组成一个偶数最接近的两个素数

查找组成一个偶数最接近的两个素数_牛客题霸_牛客网 (nowcoder.com) 描述

任意一个偶数(大于2)都可以由2个素数组成,组成偶数的2个素数有很多种情况,本题目要求输出组成指定偶数的两个素数差值最小的素数对。

数据范围:输入的数据满足 4≤n≤1000

输入描述:

输入一个大于2的偶数

输出描述:

从小到大输出两个素数

示例1

输入:

20

输出:

7

13

示例2

输入:

4

输出:

2

2

思路:

本题首先需要判断素数,素数表示除过1和本身,不能被其它数整除。通过循环遍历来判断一个数是否为素 数。最近的两个素数应该从最中间的位置开始向两边查找

#include <iostream>
using namespace std;
#include<cmath>
bool isPrime(int num)
{
    for(int i=2;i<=sqrt(num);i++)
    {
        if(num%i==0)
        return false;
    }
    return true;
}
int main()
{
    int num=0;
    cin>>num;
    for(int i=num/2;i>=2;i--)
    {
        if(isPrime(i)&&isPrime(num-i))
        {
            cout<<min(i,num-i);
            cout<<endl;
            cout<<max(i,num-i);
            break;
        }
    }
    return 0;
}
  1. 参数解析

描述

在命令行输入如下命令:

xcopy /s c:\\ d:\\e,

各个参数如下:

参数1:命令字xcopy

参数2:字符串/s

参数3:字符串c:\\

参数4: 字符串d:\\e

请编写一个参数解析程序,实现将命令行各个参数解析出来。

解析规则:

1.参数分隔符为空格

2.对于用""包含起来的参数,如果中间有空格,不能解析为多个参数。比如在命令行输入xcopy /s "C:\\program files" "d:\"时,参数仍然是4个,第3个参数应该是字符串C:\\program files,而不是C:\\program,注意输出参数时,需要将""去掉,引号不存在嵌套情况。

3.参数不定长

4.输入由用例保证,不会出现不符合要求的输入

数据范围:字符串长度: 1≤s≤1000

进阶:时间复杂度:O(n) ,空间复杂度:O(n)

输入描述:

输入一行字符串,可以有空格

输出描述:

输出参数个数,分解后的参数,每个参数都独占一行

输入:

xcopy /s c:\\ d:\\e

输出:

4

xcopy

/s

c:\\

d:\\e

#include <iostream>
#include<string>
#include<cstring>
using namespace std;
#include<vector>

int main() {
   string buffer;
    getline(cin,buffer);//不可以用cin(容易error)
    int size=buffer.size();
    bool flag=false;
    vector<string> ret;
    string tmp="";
    for(int i=0;i<size;i++)
    {          
        if(buffer[i]=='"')//遇到分号,分号里面的都是整体
        {
            flag=!flag;
        }
        else if(!flag&&buffer[i]==' ')//遇到了正常字符串末尾,需要分割
        {
            ret.push_back(tmp);
            tmp="";
        }
        else//一般情况
        {
            tmp+=buffer[i];
        }
    }
    ret.push_back(tmp);//把最后一个也要push进去(容易error)
    cout<<ret.size()<<endl;
    for(int i=0;i<ret.size();i++)
    {
        cout<<ret[i]<<endl;
    }
}
  1. 跳石板

描述

小易来到了一条石板路前,每块石板上从1挨着编号为:1、2、3.......

这条石板路要根据特殊的规则才能前进:对于小易当前所在的编号为K的 石板,小易单次只能往前跳K的一个约数(不含1和K)步,即跳到K+X(X为K的一个非1和本身的约数)的位置。 小易当前处在编号为N的石板,他想跳到编号恰好为M的石板去,小易想知道最少需要跳跃几次可以到达。

例如:

N = 4,M = 24:

4->6->8->12->18->24

于是小易最少需要跳跃5次,就可以从4号石板跳到24号石板

输入描述:

输入为一行,有两个整数N,M,以空格隔开。 (4 ≤ N ≤ 100000) (N ≤ M ≤ 100000)

输出描述:

输出小易最少需要跳跃的步数,如果不能到达输出-1

示例1

输入:

4 24

输出:

5

题目的意思是从N开始,最少需要累加几步可以变成指定的数字M,每次累加的值为当前值的一个约数。 【解题思路】: 将1 - M个石板看做一个结果数组stepNum,每个stepNum[i]储存着从起点到这一步最小的步数,其中0为不 能到达。 从起点开始对stepNum进行遍历,先求i的所有约数(即从stepNum[i]能走的步数),然后更新那 几个能到达的位置的最小步数。如果不能到达则更新为此时位置的最小步数 + 1,如果是能到达的就更新为 min(已记录的最小步数,此处的最小步数 + 1)),遍历一遍后得到结果

#include <iostream>
using namespace std;
#include<vector>
#include<cmath>
#include<algorithm>
#include<limits.h>

vector<int> NumberHelp(int n) {
    vector<int> tmp;
    for (int i = 2; i <= sqrt(n); i++) { //1.err
        if (n % i == 0) {
            tmp.push_back(i);
            if (n / i != i)
                tmp.push_back(n / i);
        }
    }
    return tmp;
}
int MinStep(int n, int m) {
    vector<int> minstep(m + 1, INT_MAX);
    minstep[n] = 0; //只需要0步就可以到达n
    for (int i = n; i < m; i++) {
        if (minstep[i] == INT_MAX)
            continue;
        vector<int> retnum = NumberHelp(i); //计算从n到m[n,m)每一点的约数
        //数组表示的状态是从前面跳过来的最小步数
        for (int j = 0; j < retnum.size(); j++) {
            if ((i + retnum[j]) <= m && minstep[i] != INT_MAX)
                minstep[i + retnum[j]] = min(minstep[i] + 1, minstep[i + retnum[j]]);
        }
    }
    return minstep[m]==INT_MAX?-1:minstep[m];
}
int main() {
    int N = 0;
    int M = 0;
    cin >> N >> M;
    int step = MinStep(N, M); //从N跳到M至少需要多少步
    cout << step;
    return 0;

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值