华为机试训练做题总结(三)

时间:2022-06-15 18:53:14

54. 挑7

题目描述 :
输出7有关数字的个数,包括7的倍数,还有包含7的数字(如17,27,37…70,71,72,73…)的个数

思路分析:
这个问题有一个很好的解决办法就是将数字转为字符型,然后查找看字符里面有没有的符合条件的 字符 ,然后再判断是否数字能否整除7
代码:

#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
while(cin>>n){
//分为两个存在7倍数 和 数字里有7的数字
int count=0;
string s;
int res=0;
for(int i=7;i<=n;i++){
stringstream ss;
ss<<i;
ss>>s;
if(s.find('7')!=s.npos || i%7 ==0){
count++;
}
}
cout<<count<<endl;
}
return 0;
}

或者

#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
while(cin>>n){
int cnt=0;
for(int i=7;i<=n;i++){
int temp=i;
if(i%7==0){
cnt++;
}else{
while(temp!=0){
if(temp%10==7)
{
++cnt;
break;
}
temp=temp/10;
}
}

}
cout<<cnt<<endl;
}
return 0;
}

55. INOC产品部完全数计算

题目描述 :
完全数(Perfect number),又称完美数或完备数,是一些特殊的自然数。

它所有的真因子(即除了自身以外的约数)的和(即因子函数),恰好等于它本身。

例如:28,它有约数1、2、4、7、14、28,除去它本身28外,其余5个数相加,1+2+4+7+14=28。

给定函数count(int n),用于计算n以内(含n)完全数的个数。计算范围, 0 < n <= 500000

返回n以内完全数的个数。 异常情况返回-1

思路分析:
这个计算还是比较简单,但是我感觉我的方法应该不是计算速度最快的。主要思想就是遍历计算。
代码:

#include<bits/stdc++.h>
using namespace std;
bool perfect_num(int n){
vector<int>sv;
for(int i=1;i<n;i++){
if(n%i==0)
{
sv.push_back(i);
}

}
int sum=0;
for(int i=0;i<sv.size();i++){
sum+=sv[i];
}
if(sum==n)
return true;
else
return false;
}
int main(){
int n;
while(cin>>n){
int count=0;
for(int i=1;i<=n;i++){
if(perfect_num(i))
count++;
}
cout<<count<<endl;
}
return 0;
}

更加优化的计算方式:
#include<bits/stdc++.h>
using namespace std;
bool is_perfect_num(int i){
int sum=0;
int j=1;
int t=i/2;
while(j<t){
if(i%j==0){
sum+=j;
if(j!=1){
t=i/j;
if(j!=i/j)
sum+=i/j;
}
}
++j;
if(sum>i)
return false;
}
return (sum==i)?true:false;
}
int count_perfect_num(int n){
if(n<=0 || n>500000) return -1;
int cnt=0;
for(int i=1;i<=n;i++){
if(is_perfect_num(i))
++cnt;
}
return cnt;
}

int main(){
int range;
while(cin>>range){
cout<<count_perfect_num(range)<<endl;
}
return 0;
}

56. 高精度整数加法

题目描述 :
在计算机中,由于处理器位宽限制,只能处理有限精度的十进制整数加减法,比如在32位宽处理器计算机中,
参与运算的操作数和结果必须在-231~231-1之间。如果需要进行更大范围的十进制整数加法,需要使用特殊
的方式实现,比如使用字符串保存操作数和结果,采取逐位运算的方式。如下:
9876543210 + 1234567890 = ?
让字符串 num1=”9876543210”,字符串 num2=”1234567890”,结果保存在字符串 result = “11111111100”。
-9876543210 + (-1234567890) = ?
让字符串 num1=”-9876543210”,字符串 num2=”-1234567890”,结果保存在字符串 result = “-11111111100”。

思路分析:
这个题目就是通过
代码:

链接:https://www.nowcoder.com/questionTerminal/49e772ab08994a96980f9618892e55b6
来源:牛客网

#include <iostream>
#include <algorithm>
#include <sstream>
using namespace std;
int strComp(string &s1, string &s2)//返回0,表示len1>len2
{
    int len1 = s1.length();
    int len2 = s2.length();
    if (len1>len2)
        return 0;
    else if (len1<len2)
        return 1;
    else
    {
        if (s1 >= s2)
            return 0;
        else
            return 1;
    }
}
string itos(long long tmp)
{
    stringstream ss;
    ss << tmp;
    string s1 = ss.str();
    return s1;
}
 
string add1(string numStr1, string numStr2) //两个都是正
{
    string res;
    int c = 0, temp;
    if (numStr1.size() != numStr2.size())
    {                                           //长度不同先补零
        while (numStr1.size() < numStr2.size())
        {
            numStr1.insert(0, 1, '0');
        }
        while (numStr1.size() > numStr2.size())
        {
            numStr2.insert(0, 1, '0');  //在0下标元素前面插一个0
        }
    }
 
    for (int i = numStr1.size() - 1; i >= 0; i--)
    {                                                    //按位相加,从低位开始
        temp = (numStr1[i] - '0') + (numStr2[i] - '0') + c;
        if (temp>9)
        {
            temp = temp % 10;
            c = 1;        
        }
        else
            c = 0;
        res += itos(temp);
    }
    if (c == 1)  res += '1';//最高位还有进位,则补1个'1'
    reverse(res.begin(), res.end());//逆置字符串后结果就是相加后的值(res是从低位往里添加字符的)
    return res;
}
 
 
 
 
string add2(string numStr1, string numStr2) //两个都是负
{
    string res;
    int c = 0, temp;
    if (numStr1.size() != numStr2.size())
    {                                           //长度不同先补零
        while (numStr1.size() < numStr2.size())
        {
            numStr1.insert(1, 1, '0');
        }
        while (numStr1.size() > numStr2.size())
        {
            numStr2.insert(1, 1, '0');  //在1下标元素前面插一个0
        }
    }
    for (int i = numStr1.size() - 1; i>0; i--)
    {                                                  //最高位不管
        temp = (numStr1[i] - '0') + (numStr2[i] - '0') + c;
        if (temp>9)
        {
            temp = temp % 10;
            c = 1;
        }
        else
            c = 0;
        res += itos(temp);
    }
    if (c)res += '1';//最高位
    res += '-';      //添加'-'
    reverse(res.begin(), res.end());
    return res;
}
 
string add3(string numStr1, string numStr2) //一正一负
{
    string res;
    int flag = 0;
    int c = 0, temp;
    string a, b;//a-b a是被减数 b是减数 带负号的给减数
    if (numStr1[0] == '-') { b = numStr1; a = numStr2; }
    else{ b = numStr2; a = numStr1; }
    b = b.substr(1);
    if (a.size() != b.size())
    {                                           //长度不同先补零
        while (a.size() < b.size())
        {
            a.insert(0, 1, '0');
        }
        while (a.size() > b.size())
        {
            b.insert(0, 1, '0');  //在0下标元素前面插一个0
        }
    }
    if (strComp(a, b) == 1)
    {
        string t = b;
        b = a;
        a = t;
        flag = 1;
    }
 
    for (int i = a.size() - 1; i>=0; i--)
    {                                                  //最高位不管
        temp = (a[i] - '0')-(b[i] - '0')-c;
        if (temp<0)
        {
            temp =temp+10;
            c = 1;
        }
        else
            c = 0;
        res += itos(temp);
    }
    if(flag==1)res += '-';      //添加'-'
    reverse(res.begin(), res.end());
    return res;
}
 
int main()
{
    string numStr1, numStr2;
    while (cin >> numStr1 >> numStr2)
    {
        string result;
        if (numStr1[0] != '-'&&numStr2[0] != '-') result = add1(numStr1, numStr2);
        else if (numStr1[0] == '-'&&numStr2[0] == '-') result = add2(numStr1, numStr2);
        else result = add3(numStr1, numStr2);
        cout << result << endl;
    }
    system("pause");
    return 0;
}