九度OJ题目1101--1150解题练习(四)

题目1101:计算表达式

题目描述:

对于一个不存在括号的表达式进行计算

输入:

存在多种数据,每组数据一行,表达式不存在空格

输出:

输出结果

方法:
从第一个位置起,依次获得操作数,每次获取一个操作数的断位置就是‘+’‘-’‘*’‘/’出现的时候,然后利用栈,遇到优先级高的*或者/就计算结果然后压栈,遇到+或者-就简单处理(比如-,应该将相应的数变为复数)压栈
样例输入:
6/2+3+3*4
样例输出:
18

C++程序实现如下:

#include <iostream>
#include <stack>
using namespace std;
 
string str;
int pos;
 
double getNum()
{
    double v = 0;
    for (; pos<str.length(); pos++)
    {
        if (str[pos]>'9' || str[pos] < '0')
        {
            break;
        }
        v *= 10;
        v += str[pos] - '0';
    }
    return 1.0*v;
}
 
int main(int argc,char* argv[])
{
    double a, b;
    double v;
    while (cin>>str)
    {
        stack<double> s;
        pos = 0;
        s.push(getNum());
        while (pos < str.length())
        {
            if (str[pos] == '*')
            {
                pos++;
                a = s.top();
                s.pop();
                b = getNum();
                s.push(a*b);
            }
            if (str[pos] == '/')
            {
                pos++;
                a = s.top();
                s.pop();
                b = getNum();
                s.push(a / b);
            }
            if (str[pos] == '+')
            {
                pos++;
                s.push(getNum());
            }
            if (str[pos] == '-')
            {
                pos++;
                s.push(-1.0*getNum());
            }
        }
        v = 0;
        while (!s.empty())
        {
            v += s.top();
            s.pop();
        }
        cout << v << endl;
    }
    return 0;
}
/**************************************************************
    Problem: 1101
    User: EbowTang
    Language: C++
    Result: Accepted
    Time:0 ms
    Memory:1524 kb
****************************************************************/

题目1106:数字之和

题目描述:

对于给定的正整数 n,计算其十进制形式下所有位置数字之和,并计算其平方的各位数字之和。

输入:

每行输入数据包括一个正整数n(0<n<40000),如果n=0 表示输入结束,并不用计算。

输出:

对于每个输入数据,计算其各位数字之和,以及其平方值的数字之和,输出在一行中,之间用一个空格分隔,但行末不要有空格。

样例输入:
4
12
97
39999
0
样例输出:
4 7
3 9
16 22
39 36
#include "vector"
#include <iostream>
 
using namespace std;
 
int main()
{
    int n = 0;
    while (cin >> n)
    {
        if (n == 0)
            continue;
        int m = n*n;
        int sum = 0;
        while (n)
        {
            sum = sum + n % 10;
            n = n / 10;
        }
        cout << sum << " ";
        sum = 0;
        while (m)
        {
            sum = sum + m % 10;
            m = m / 10;
        }
        cout << sum << endl;
         
    }
    return 0;
}
/**************************************************************
    Problem: 1106
    User: EbowTang
    Language: C++
    Result: Accepted
    Time:0 ms
    Memory:1520 kb
****************************************************************/

题目1108:堆栈的使用

题目描述:

    堆栈是一种基本的数据结构。堆栈具有两种基本操作方式,push 和 pop。Push一个值会将其压入栈顶,而 pop 则会将栈顶的值弹出。现在我们就来验证一下堆栈的使用。

输入:

     对于每组测试数据,第一行是一个正整数 n,0<n<=10000(n=0 结束)。而后的 n 行,每行的第一个字符可能是'P’或者'O’或者'A’;如果是'P’,后面还会跟着一个整数,表示把这个数据压入堆栈;如果是'O’,表示将栈顶的值 pop 出来,如果堆栈中没有元素时,忽略本次操作;如果是'A’,表示询问当前栈顶的值,如果当时栈为空,则输出'E'。堆栈开始为空。

输出:

    对于每组测试数据,根据其中的命令字符来处理堆栈;并对所有的'A’操作,输出当时栈顶的值,每个占据一行,如果当时栈为空,则输出'E’。当每组测试数据完成后,输出一个空行。

样例输入:
3
A
P 5
A
4
P 3
P 6
O 
A
0
样例输出:
E
5

3
#include <iostream>
#include "algorithm"
 
using namespace std;
 
class Stack
{
public:
    Stack(int size)
    {
        elements = new int[size];
        top = -1;
    }
    ~Stack()
    {
        delete[] elements;
        elements = NULL;
    }
    bool push(int ndata);//压入元素到栈顶
    void popTop();//弹出栈顶元素
    void getTop();//获取栈顶元素
private:
    int *elements;
    int top;                     //始终指向栈顶,top=0,就表示有一个数据了  
};
 
//压入元素
bool Stack::push(int ndata)
{
    top++;
    elements[top]=ndata;//从栈顶压入元素 
    return true;
}
 
//获取栈顶元素
void Stack::getTop()
{
    if (top == -1)//栈空  
        cout << "E" << endl;
    else
        cout << elements[top] << endl; //返回当前栈顶元素 
}
 
//除去栈顶元素
void Stack::popTop()
{
    if (top > -1)                    
        top--;
}
 
int main()
{
    int n = 0;
    while (cin >> n && n>0 && n <= 10000)
    {
        cin.get();//换新行准备让ch接收字符,如果没有将错误,找了好久才发现,他妈的
        Stack s(10000);
        char ch = '0';
        int num = 0;
        for (int i = 0; i < n; i++)
        {
            cin >> ch;
            switch (ch)
            {
            case 'P'://压栈栈顶
                cin >> num;
                s.push(num);
                break;
            case 'A'://访问栈顶
                s.getTop();
                break;
            case 'O'://弹出栈顶
                s.popTop();
                break;
            default:
                break;
            }
        }
        cout << endl;
    }
}
/**************************************************************
    Problem: 1108
    User: EbowTang
    Language: C++
    Result: Accepted
    Time:140 ms
    Memory:1520 kb
****************************************************************/


题目1109:连通图

题目描述:

    给定一个无向图和其中的所有边,判断这个图是否所有顶点都是连通的。

输入:

    每组数据的第一行是两个整数 n 和 m(0<=n<=1000)。n 表示图的顶点数目,m 表示图中边的数目。如果 n 为 0 表示输入结束。随后有 m 行数据,每行有两个值 x 和 y(0<x, y <=n),表示顶点 x 和 y 相连,顶点的编号从 1 开始计算。输入不保证这些边是否重复。

输出:

    对于每组输入数据,如果所有顶点都是连通的,输出"YES",否则输出"NO"。

样例输入:
4 3
1 2
2 3
3 2
3 2
1 2
2 3
0 0
样例输出:
NO
YES
#include "vector"
#include "string"
#include "algorithm"
#include <iostream>
#include "stack"
#include <cmath>
#include <set>
 
 
using namespace std;
 
class UFSet
{
public:
    UFSet(int nsize)
    {
        parent = new int[nsize + 1];
    }
    ~UFSet()
    {
        delete[] parent;
        parent = NULL;
    }
 
    // 初始化每个顶点的祖先为自身
    void makeSet(int n);
 
    // 找到元素x的祖先元素   
    int findSet(int x);
 
    void unionSet(int x, int y);
     
    int getSets(int n);
private:
    int *parent;//存放祖先节点,例如x=parent[i],元素i的祖先节点为元素x      
};
 
void UFSet::makeSet(int n) //初始化      
{
    for (size_t i = 1; i <= n; i++)
        parent[i] = i;
}
 
int UFSet::findSet(int x)
{
 
    if (parent[x] == x)
        return x;
 
    parent[x] = findSet(parent[x]);
    return parent[x];
}
 
void UFSet::unionSet(int x, int y)
{ 
    int ux = findSet(x);
    int uy = findSet(y);
    if (ux != uy)
        parent[ux] = uy;
}
 
int UFSet::getSets(int n)
{
    int count = 0;
    for (int i = 1; i <= n; i++)
    {//如果存在某一个节点的祖先是自身说明他是孤立的或者本身就是祖先  
        if (parent[i] == i)
            count++;
    }
    return count;
}
 
int main()
{
    int n = 0, m = 0;
    while (cin >> n >> m,n>0)
    {
        UFSet uset(n);
        uset.makeSet(n);//初始化每个城市的祖先为自身  
        int avex = 0,bvex=0;
        for (int i = 1; i <= m; i++)
        {
            cin >> avex >> bvex;
            uset.unionSet(avex,bvex);
        }
 
        if (uset.getSets(n) == 1)
            cout << "YES" << endl;
        else
            cout << "NO" << endl;
    }
 
    return 0;
}
 
/**************************************************************
    Problem: 1109
    User: EbowTang
    Language: C++
    Result: Accepted
    Time:40 ms
    Memory:1520 kb
****************************************************************/





题目1113:二叉树

题目描述:

<C/C++练习>九度OJ题目1101--1150解题练习(四)_第1张图片 


    如上所示,由正整数1,2,3……组成了一颗特殊二叉树。我们已知这个二叉树的最后一个结点是n。现在的问题是,结点m所在的子树中一共包括多少个结点。

    比如,n = 12,m = 3那么上图中的结点13,14,15以及后面的结点都是不存在的,结点m所在子树中包括的结点有3,6,7,12,因此结点m的所在子树中共有4个结点。

输入:

    输入数据包括多行,每行给出一组测试数据,包括两个整数m,n (1 <= m <= n <= 1000000000)。最后一组测试数据中包括两个0,表示输入的结束,这组数据不用处理。

输出:

    对于每一组测试数据,输出一行,该行包含一个整数,给出结点m所在子树中包括的结点的数目。

样例输入:
3 120 0
样例输出:
4

#include <iostream>
#include "stack"
#include <cmath> 
 
using namespace std;
//先不算最后一层,统计出节点数
//算出最后一层有多少节点
int main()
{
    int m, n, i;
    while (cin>>m>>n) 
    {
        if (m == 0 && n == 0) 
            break;
        //注意这里的log是以2为低
        int h1 = (int)(log(m) / log(2)) + 1; // m的树高,以题举例:h1=2  
        int h2 = (int)(log(n) / log(2)) + 1; // n的树高,h2=4
        int left = m;//3
        int right = m;//3
        int count = 0;//记录节点数
        int h = h2 - h1; // 结点n与结点m的高度差  
        count = pow(2, h) - 1; //先不算最后一层,计算结点m所拥有的子节点数  
        for (i = 1; i <= h; i++) 
        {//算出节点m在共有n个节点时的最左最右节点位置
            left = 2 * left;
            right = 2 * right + 1;
        } 
        //求出最后一层结点m的可能最左与最右结点  
        if (right <= n)
            count += right - left + 1;
        else if (left <= n)
            count += n - left + 1;
        cout << count << endl;
    }
     
    return 0;
}
/**************************************************************
    Problem: 1113
    User: EbowTang
    Language: C++
    Result: Accepted
    Time:0 ms
    Memory:1628 kb
****************************************************************/

题目1115:数字求和

题目描述:

给定一个正整数a,以及另外的5个正整数,问题是:这5个整数中,小于a的整数的和是多少?

输入:

输入一行,只包括6个小于100的正整数,其中第一个正整数就是a。

输出:

可能有多组测试数据,对于每组数据,
输出一行,给出一个正整数,是5个数中小于a的数的和。

样例输入:
10 1 2 3 4 11
样例输出:
10
#include "vector"
#include <iostream>
 
using namespace std;
 
int main()
{
    vector<int> vec(6,0);
    while (cin >> vec[0]>>vec[1]>>vec[2]>>vec[3]>>vec[4]>>vec[5] )
    {
        int sum = 0;
        for (size_t i = 1; i < 6; i++)
        {
            if (vec[i]<vec[0])
                sum += vec[i];
        }
        cout << sum << endl;
    }
    return 0;
}
/**************************************************************
    Problem: 1115
    User: EbowTang
    Language: C++
    Result: Accepted
    Time:110 ms
    Memory:1520 kb
****************************************************************/

题目1117:整数奇偶排序

题目描述:

输入10个整数,彼此以空格分隔。重新排序以后输出(也按空格分隔),要求:
1.先输出其中的奇数,并按从大到小排列;
2.然后输出其中的偶数,并按从小到大排列。

输入:

任意排序的10个整数(0~100),彼此以空格分隔。

输出:

可能有多组测试数据,对于每组数据,按照要求排序后输出,由空格分隔。

样例输入:
4 7 3 13 11 12 0 47 34 98
样例输出:
47 13 11 7 3 0 4 12 34 98
提示:

1. 测试数据可能有很多组,请使用while(cin>>a[0]>>a[1]>>...>>a[9])类似的做法来实现;
2. 输入数据随机,有可能相等。

#include "vector"
#include "string"
#include <iostream>
#include "algorithm"
 
using namespace std;
 
int main()
{
    vector<int> a(10, 0);
    while (cin >> a[0] >> a[1] >> a[2] >> a[3] >> a[4] >> a[5] >> a[6] >> a[7] >> a[8] >> a[9])
    {
        vector<int> subodd,subeven;
        for (size_t i = 0; i < 10; i++)
        {
            if (a[i] % 2 == 1)
                subodd.push_back(a[i]);
            else
                subeven.push_back(a[i]);
        }
        sort(subodd.begin(),subodd.end());
        sort(subeven.begin(), subeven.end());
        for (int i = subodd.size() - 1; i >= 0; i--)
        {
            if (subodd.size() == 10 && i == 0)
                cout << subodd[i] << endl;
            else
                cout << subodd[i] << " ";
        }
        for (int i = 0; i < subeven.size(); i++)
        {
            if (i == subeven.size() - 1)
                cout << subeven[i] << endl;
            else
                cout << subeven[i] << " ";
             
        }
    }
    return 0;
}
/**************************************************************
    Problem: 1117
    User: EbowTang
    Language: C++
    Result: Accepted
    Time:200 ms
    Memory:1520 kb
****************************************************************/

题目1121:首字母大写

题目描述:

对一个字符串中的所有单词,如果单词的首字母不是大写字母,则把单词的首字母变成大写字母。
在字符串中,单词之间通过空白符分隔,空白符包括:空格(' ')、制表符('\t')、回车符('\r')、换行符('\n')。

输入:

输入一行:待处理的字符串(长度小于100)。

输出:

可能有多组测试数据,对于每组数据,
输出一行:转换后的字符串。

样例输入:
if so, you already have a google account. you can sign in on the right.
样例输出:
If So, You Already Have A Google Account. You Can Sign In On The Right.
#include "string"
#include <iostream>
using namespace std;
int main()
{
    string str;
    while (getline(cin, str))
    {
        //'a'==97,'A'==65
        if (str[0] <= 'z' && str[0] >= 'a')
            str[0] = str[0] - 32;
        for (int i = 1; i < str.size(); i++)
        {//将空格等后面的字符由小写变为大写
            if (str[i - 1] == ' ' || str[i - 1] == '\t' || str[i - 1] == '\r' || str[i - 1] == '\n')
            {
                if (str[i] <= 'z' && str[i] >= 'a')
                    str[i] = str[i] - 32;
            }
        }
        cout << str << endl;
    }
    return 0;
}
/**************************************************************
    Problem: 1121
    User: EbowTang
    Language: C++
    Result: Accepted
    Time:10 ms
    Memory:1520 kb
****************************************************************/

题目1125:大整数的因子

题目描述:

已知正整数k满足2<=k<=9,现给出长度最大为30位的十进制非负整数c,求所有能整除c的k.

输入:

若干个非负整数c,c的位数<=30
每行一个c,当c=-1时中止
(不要对-1进行计算!)

输出:

每一个c的结果占一行
1) 若存在满足 c%k == 0 的k,输出所有这样的k,中间用空格隔开,最后一个k后面没有空格。
2) 若没有这样的k则输出"none"

样例输入:
30
72
13
-1
样例输出:
2 3 5 6
2 3 4 6 8 9
none
提示:

注意整数溢出问题
不要对-1进行计算

#include "vector"
#include "string"
#include "algorithm"
#include <iostream>
#include "stack"
#include "math.h"  
 
using namespace std;
 
//大整数的相除或者相乘问题一般可以模拟手算过程
bool isBigDiv(const string &src, int k)
{
    int val = 0, carry = 0;
    for (int i = 0; i < src.length(); i++)
    {//模拟手算除法
        val = (src[i] - '0') + carry * 10;
        carry = val % k;
    }
    if (carry == 0)
        return true;
    else
        return false;
}
 
int main(void)
{
    string str;
    while (cin>>str)
    {
        if (str == "-1")
            break;
        vector<int> vec;
 
        for (int i = 2; i <= 9; i++)
            if (isBigDiv(str, i))
                vec.push_back(i);
         
        if (vec.size() == 0)
        {
            cout << "none" << endl;
        }
        else
        {
            for (int i = 0; i < vec.size() - 1; i++)
                cout << vec[i] << " ";
            cout << vec[vec.size() - 1] << endl;
 
        }
    }
    return 0;
}
/**************************************************************
    Problem: 1125
    User: EbowTang
    Language: C++
    Result: Accepted
    Time:170 ms
    Memory:1520 kb
****************************************************************/

题目1128:求平均年龄

题目描述:

班上有学生若干名,给出每名学生的年龄(整数),求班上所有学生的平均年龄,保留到小数点后两位。

输入:

第一行有一个整数n(1<= n <= 100),表示学生的人数。其后n行每行有1个整数,取值为15到25。

输出:

可能有多组测试数据,对于每组数据,
输出一行,该行包含一个浮点数,为要求的平均年龄,保留到小数点后两位。

样例输入:
2
18
17
样例输出:
17.50
提示:

要输出浮点数、双精度数小数点后2位数字,可以用下面这种形式: 
printf("%.2f", num);

#include "vector"
#include <iostream>
#include "iomanip"
 
using namespace std;
 
int main()
{
    int n = 0;
    while (cin >> n)
    {
        vector<int> stu(n);
        for (int i = 0; i < n; i++)
            cin >> stu[i];
 
        double sum = 0.0, avg = 0.0;
 
        for (int i = 0; i < n; i++)
            sum += static_cast<double>(stu[i]);
        avg = sum / n;
        cout << fixed << setprecision(2) << avg << endl;
    }
    return 0;
}
/**************************************************************
    Problem: 1128
    User: EbowTang
    Language: C++
    Result: Accepted
    Time:40 ms
    Memory:1520 kb
****************************************************************/


题目1132:与7无关的数

题目描述:

一个正整数,如果它能被7整除,或者它的十进制表示法中某个位数上的数字为7,
则称其为与7相关的数.现求所有小于等于n(n<100)的与7无关的正整数的平方和。

输入:

案例可能有多组。对于每个测试案例输入为一行,正整数n,(n<100)

输出:

对于每个测试案例输出一行,输出小于等于n的与7无关的正整数的平方和。

样例输入:
21
样例输出:
2336
#include "vector"
#include <iostream>
 
using namespace std;
 
bool BecauseOfSeven(int n);
int main()
{
    int n = 0;
    while (cin >> n)
    {
        if (n > 100)
            break;
        int sum = 0;
        for (int i = 0; i <= n;i++)
        {
            if (!BecauseOfSeven(i))
                sum = sum + i*i;
        }
        cout << sum << endl;
         
    }
    return 0;
}
bool BecauseOfSeven(int n)
{
    if (n % 7 == 0)
        return true;
    int m = n;
    while (m)
    {
        if (m % 10 == 7)
            return true;
        m = m / 10;
    }
    return false;
}
/**************************************************************
    Problem: 1132
    User: EbowTang
    Language: C++
    Result: Accepted
    Time:20 ms
    Memory:1520 kb
****************************************************************/

题目1133:学分绩点

题目描述:

北京大学对本科生的成绩施行平均学分绩点制(GPA)。既将学生的实际考分根据不同的学科的不同学分按一定的公式进行计算。
公式如下:
实际成绩 绩点
90——100 4.0
85——89 3.7
82——84 3.3
78——81 3.0
75——77 2.7
72——74 2.3
68——71 2.0
64——67 1.5
60——63 1.0
60以下 0
1.一门课程的学分绩点=该课绩点*该课学分
2.总评绩点=所有学科绩点之和/所有课程学分之和
现要求你编写程序求出某人A的总评绩点(GPA)。

输入:

第一行 总的课程数n(n<10);
第二行 相应课程的学分(两个学分间用空格隔开);
第三行 对应课程的实际得分;
此处输入的所有数字均为整数。

输出:

输出有一行,总评绩点,精确到小数点后2位小数。(printf("%.2f",GPA);)

样例输入:
5
4 3 4 2 3
91 88 72 69 56
样例输出:
2.52
#include "vector"
#include <iostream>
#include <iomanip>
 
using namespace std;
double getPA(int n)
{
    if (n >= 90 && n <= 100)
        return 4.0;
    else if (n >= 85 && n <= 89)
        return 3.7;
    else if (n >= 82 && n <= 84)
        return 3.3;
    else if (n >= 78 && n <= 81)
        return 3.0;
    else if (n >= 75 && n <= 77)
        return 2.7;
    else if (n >= 72 && n <= 74)
        return 2.3;
    else if (n >= 68 && n <= 71)
        return 2.0;
    else if (n >= 64 && n <= 67)
        return 1.5;
    else if (n >= 60 && n <= 63)
        return 1.0;
    else
        return 0.0;
}
int main()
{
    int n = 0;
    while (cin >> n && n <10 )
    {
        vector<int> vecGpa(n);
        for (int i = 0; i < n; i++)
            cin >> vecGpa[i];//获取学分
         
        vector<int> vecSorce(n);
        for (int i = 0; i < n; i++)
            cin >> vecSorce[i];//获取分数
 
        int sumMark = 0;
        for (int i = 0; i < n; i++)
            sumMark += vecGpa[i];//获取学分之和
 
        double sumGpa = 0.0;
        for (int i = 0; i < n; i++)
            sumGpa += getPA(vecSorce[i])*vecGpa[i];//获取各科成绩下相应的绩点
         
        cout << fixed << setprecision(2) << sumGpa / sumMark << endl;
    }
    return 0;
}
/**************************************************************
    Problem: 1133
    User: EbowTang
    Language: C++
    Result: Accepted
    Time:10 ms
    Memory:1520 kb
****************************************************************/

题目1138:进制转换

题目描述:

将一个长度最多为30位数字的十进制非负整数转换为二进制数输出。

输入:

多组数据,每行为一个长度不超过30位的十进制非负整数。
(注意是10进制数字的个数可能有30个,而非30bits的整数)

输出:

每行输出对应的二进制数。

样例输入:
0
1
3
8
样例输出:
0
1
11
1000

#include "vector"
#include "string"
#include <iostream>
#include "algorithm"
using namespace std;
 
int devide(int len, vector<int> &ivec)
{//vec[i]是高位,vec[i+1]是相对的低位
    int carry = 0;
    for (int i = 0; i<len; i++)
    {//模拟这个数除以2的手算过程(从高位开始处理),比如输入32,本次循环完后将变成16
        int num = (carry * 10 + ivec[i]) / 2;
        carry = ivec[i] % 2;//求除以2后的余数,举例51/2,num=2,但是carry=1
        ivec[i] = num;
    }
    return carry;
}
 
//判断ivec是否全为0
bool isAllZero(int len,vector<int> &ivec)
{
    for (int i = len - 1; i >= 0; i--)
    {
        if (ivec[i] != 0)
            return false;
    }
    return true;
}
 
int main()
{
    string src;//用字符串接收输入的数字,可接收任意长度(但是别太大了)
    while (cin >> src)
    {
        vector<int> ivec(200, 0);//将字符串数字转换成整型数字,顺序接收
        vector<int> ires(400, 0);//存放二进制结果
        int nsize = 0;
        while (nsize < src.size())
        {//按照顺序转换,高位在数组前面
            ivec[nsize] = src[nsize] - '0';
            nsize++;
        }
 
        int reslen = 0;
        do
        {//循环一次数字少一半(数组的中的值均变化),获得当次的二进制数
            ires[reslen++] = devide(nsize,ivec);
        } while (!isAllZero(nsize, ivec));
 
        for (int i = reslen - 1; i >= 0; i--)
            cout << ires[i];
 
        cout << endl;
    }
    return 0;
}
/**************************************************************
    Problem: 1138
    User: EbowTang
    Language: C++
    Result: Accepted
    Time:250 ms
    Memory:1520 kb
****************************************************************/








你可能感兴趣的:(数据结构,算法,ACM,九度)