算法学习——华为机考题库6(HJ36 - HJ40)
HJ36 字符串加密
描述
有一种技巧可以对数据进行加密,它使用一个单词作为它的密匙。下面是它的工作原理:首先,选择一个单词作为密匙,如TRAILBLAZERS。如果单词中包含有重复的字母,只保留第1个,将所得结果作为新字母表开头,并将新建立的字母表中未出现的字母按照正常字母表顺序加入新字母表。如下所示:
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
T R A I L B Z E S C D F G H J K M N O P Q U V W X Y (实际需建立小写字母的字母表,此字母表仅为方便演示)
上面其他用字母表中剩余的字母填充完整。在对信息进行加密时,信息中的每个字母被固定于顶上那行,并用下面那行的对应字母一一取代原文的字母(字母字符的大小写状态应该保留)。因此,使用这个密匙, Attack AT DAWN (黎明时攻击)就会被加密为Tpptad TP ITVH。
请实现下述接口,通过指定的密匙和明文得到密文。
数据范围: 1≤n≤100 ,保证输入的字符串中仅包含小写字母
输入描述:
先输入key和要加密的字符串
输出描述:
返回加密后的字符串
示例
代码解析
#include <algorithm>
#include <iostream>
#include <map>
#include <string>
#include <vector>
using namespace std;
int main() {
string key,Str;
cin>>key;
cin>>Str;
vector<int> Vec;
for(int i=0;i<key.size();i++)
{
int tmp = 0;
if(key[i] >= 'a' && key[i] <= 'z' ) tmp = key[i] - 'a';
else if( key[i] >= 'A' && key[i] <= 'Z') tmp = key[i] - 'A';
if(find(Vec.begin(), Vec.end(), tmp) == Vec.end())
Vec.push_back(tmp);
}
for(int i = 0 ; i <26 ; i++ )
{
if(find(Vec.begin(), Vec.end(), i) == Vec.end())
Vec.push_back(i);
}
for(int i=0 ; i<Str.size() ;i++)
{
int tmp = 0;
if(Str[i] >= 'a' && Str[i] <= 'z' )
{
tmp = Str[i] - 'a';
cout<<(char)('a' + Vec[tmp]);
}
else if( Str[i] >= 'A' && Str[i] <= 'Z')
{
tmp = Str[i] - 'A';
cout<<(char)('A' + Vec[tmp]);
}
}
}
// 64 位输出请用 printf("%lld")
HJ37 统计每个月兔子的总数
描述
有一种兔子,从出生后第3个月起每个月都生一只兔子,小兔子长到第三个月后每个月又生一只兔子。
例子:假设一只兔子第3个月出生,那么它第5个月开始会每个月生一只兔子。
一月的时候有一只兔子,假如兔子都不死,问第n个月的兔子总数为多少?
**数据范围:**输入满足 1≤n≤31
输入描述:
输入一个int型整数表示第n个月
输出描述:
输出对应的兔子总数
示例
代码解析
#include <iostream>
#include <vector>
using namespace std;
int main() {
int N;
cin>>N;
vector<int> dp(N+1,0);
dp[1] = 1;
dp[2] = 1;
for(int i=3 ; i<=N ;i++)
{
dp[i] = dp[i-1] + dp[i-2];
}
cout<< dp[N];
}
// 64 位输出请用 printf("%lld")
HJ38 求小球落地5次后所经历的路程和第5次反弹的高度
描述
假设一个球从任意高度自由落下,每次落地后反跳回原高度的一半; 再落下, 求它在第5次落地时,共经历多少米?第5次反弹多高?
**数据范围:**输入的小球初始高度满足 1≤n≤1000 ,且保证是一个整数
输入描述:
输入起始高度,int型
输出描述:
分别输出第5次落地时,共经过多少米以及第5次反弹多高。
注意:你可以认为你输出保留六位或以上小数的结果可以通过此题。
示例
代码解析
#include <iostream>
using namespace std;
int main() {
double h;
double path = 0;
cin>>h;
for(int i=0 ; i<4 ;i++)
{
path += h;
h /=2;
path += h;
}
path += h;
cout<<path<<endl;
cout<<h/2;
}
// 64 位输出请用 printf("%lld")
HJ39 判断两个IP是否属于同一子网
描述
IP地址是由4个0-255之间的整数构成的,用"."符号相连。
二进制的IP地址格式有32位,例如:10000011,01101011,00000011,00011000;每八位用十进制表示就是131.107.3.24
子网掩码是用来判断任意两台计算机的IP地址是否属于同一子网络的根据。
子网掩码与IP地址结构相同,是32位二进制数,由1和0组成,且1和0分别连续,其中网络号部分全为“1”和主机号部分全为“0”。
你可以简单的认为子网掩码是一串连续的1和一串连续的0拼接而成的32位二进制数,左边部分都是1,右边部分都是0。
利用子网掩码可以判断两台主机是否在同一子网中。
若两台主机的IP地址分别与它们的子网掩码进行逻辑“与”运算(按位与/AND)后的结果相同,则说明这两台主机在同一子网中。
示例:
I P 地址 192.168.0.1
子网掩码 255.255.255.0
转化为二进制进行运算:
I P 地址 11000000.10101000.00000000.00000001
子网掩码 11111111.11111111.11111111.00000000
AND运算 11000000.10101000.00000000.00000000
转化为十进制后为:
192.168.0.0
I P 地址 192.168.0.254
子网掩码 255.255.255.0
转化为二进制进行运算:
I P 地址 11000000.10101000.00000000.11111110
子网掩码 11111111.11111111.11111111.00000000
AND运算 11000000.10101000.00000000.00000000
转化为十进制后为:
192.168.0.0
通过以上对两台计算机IP地址与子网掩码的AND运算后,我们可以看到它运算结果是一样的。均为192.168.0.0,所以这二台计算机可视为是同一子网络。
输入一个子网掩码以及两个ip地址,判断这两个ip地址是否是一个子网络。
若IP地址或子网掩码格式非法则输出1,若IP1与IP2属于同一子网络输出0,若IP1与IP2不属于同一子网络输出2。
注:
有效掩码与IP的性质为:
- 掩码与IP每一段在 0 - 255 之间
- 掩码的二进制字符串前缀为网络号,都由‘1’组成;后缀为主机号,都由’0’组成
输入描述:
3行输入,第1行是输入子网掩码、第2,3行是输入两个ip地址
题目的示例中给出了三组数据,但是在实际提交时,你的程序可以只处理一组数据(3行)。
输出描述:
若IP地址或子网掩码格式非法则输出1,若IP1与IP2属于同一子网络输出0,若IP1与IP2不属于同一子网络输出2
示例
代码解析
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
int main() {
vector<vector<int>> date;
vector<vector<int>> result(2,vector<int>(4,0));
for(int i=0 ; i<3 ; i++)
{
vector<int> tmp;
string Str , cur;
cin>>Str;
stringstream iss(Str);
bool flag = false;
for(int j=0 ; j<4 ; j++)
{
getline(iss,cur, '.');
tmp.push_back( stoi(cur) );
if(i==0)
{
unsigned int num = stoi(cur);
num = (num << 24);
for(int j=0 ;j < 8 ; j++)
{
if( (num & 0x80000000 )== 0x80000000 && flag == true)
{
cout<<'1';
return 0;
}else if( (num & 0x80000000 )== 0 )
flag = true;
num = num<<1;
}
}
if(stoi(cur) > 255 || stoi(cur) < 0)
{
cout<<'1';
return 0;
}
}
date.push_back(tmp);
}
for(int i=0 ; i<2 ; i++)
{
for(int j=0 ; j<4 ; j++)
{
result[i][j] = date[0][j] & date[i+1][j];
}
}
if(result[0] == result[1]) cout<<'0';
else cout<<'2';
}
// 64 位输出请用 printf("%lld")
HJ40 统计字符
描述
输入一行字符,分别统计出包含英文字母、空格、数字和其它字符的个数。
数据范围:输入的字符串长度满足 1≤n≤1000
输入描述:
输入一行字符串,可以有空格
输出描述:
统计其中英文字符,空格字符,数字字符,其他字符的个数
示例
代码解析
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main() {
string Str;
getline(cin, Str);
vector<int> result(4,0);
for(int i=0 ; i < Str.size() ; i++)
{
if(( Str[i] >= 'a' && Str[i] <= 'z') || ( Str[i] >= 'A' && Str[i] <= 'Z'))
result[0]++;
else if(Str[i] == ' ') result[1]++;
else if(Str[i] >= '0' && Str[i] <= '9') result[2]++;
else result[3]++;
}
for(int i=0 ; i<4 ; i++)
cout<<result[i]<<endl;
}
// 64 位输出请用 printf("%lld")