二进制插入
链接: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移位后再按位或就好啦
查找组成一个偶数最接近的两个素数
查找组成一个偶数最接近的两个素数_牛客题霸_牛客网 (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;
}
参数解析
描述
在命令行输入如下命令:
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、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;
}