九度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:二叉樹
- 題目描述:
-
如上所示,由正整數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
****************************************************************/