杭电 OJ2090-2099

写在前面

本文记录了刷杭电 OJ2090-2099 的过程和一些想法,代码仅供参考!


2090 算菜价

Problem Description

妈妈每天都要出去买菜,但是回来后,兜里的钱也懒得数一数,到底花了多少钱真是一笔糊涂帐。现在好了,作为好儿子(女儿)的你可以给她用程序算一下了,呵呵。

Input

输入含有一些数据组,每组数据包括菜种(字串),数量(计量单位不论,一律为 double 型数)和单价(double 型数,表示人民币元数),因此,每组数据的菜价就是数量乘上单价啊。菜种、数量和单价之间都有空格隔开的。

Output

支付菜价的时候,由于最小支付单位是角,所以总是在支付的时候采用四舍五入的方法把分头去掉。最后,请输出一个精度为角的菜价总量。

Sample Input

青菜 1 2
萝卜 2 1.5
鸡腿 2 4.2

Sample Output

13.4

解题思路

四舍五入,直接保留一位输出就可以了

参考源码

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
using namespace std;
int main(void) {
double sum = 0, d, n;
string s;
while (cin >> s) {
cin >> n >> d;
sum += n * d;
}
printf("%.1f\n", sum);
return 0;
}

2091 空心三角形

Problem Description

把一个字符三角形掏空,就能节省材料成本,减轻重量,但关键是为了追求另一种视觉效果。在设计的过程中,需要给出各种花纹的材料和大小尺寸的三角形样板,通过电脑临时做出来,以便看看效果。

Input

每行包含一个字符和一个整数 n(0<n<41),不同的字符表示不同的花纹,整数 n 表示等腰三角形的高。显然其底边长为 2n-1。如果遇到@字符,则表示所做出来的样板三角形已经够了。

Output

每个样板三角形之间应空上一行,三角形的中间为空。显然行末没有多余的空格。

Sample Input

X 2
A 7
@

Sample Output

1
2
3
4
5
6
7
8
9
10
 X
XXX

A
A A
A A
A A
A A
A A
AAAAAAAAAAAAA

解题思路

没什么方法,直接按要求打印就行

参考源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
using namespace std;
int main() {
string s;
int n, flag = 0; // flag用来判断是否需要换行,只有第一次输入时不需要换行
while (cin >> s >> n) {
if (s == "@") break;
if (flag++) cout << endl; //除了第一个外,空一行再输出
for (int i = 1; i < n; i++) //遍历输出前n-1行
{
for (int j = i; j < n; j++) {
cout << " ";
}
cout << s;
for (int j = 0; j < 2 * i - 3; j++) {
cout << " ";
}
if (i == 1)
cout << endl;
else
cout << s << endl;
}
for (int i = 0; i < 2 * n - 1; i++) //最后一行
cout << s;
cout << endl;
}
return 0;
}

2092 整数解

Problem Description

有二个整数,它们加起来等于某个整数,乘起来又等于另一个整数,它们到底是真还是假,也就是这种整数到底存不存在,实在有点吃不准,你能快速回答吗?看来只能通过编程。
例如:x + y = 9,x × y = 15 ? 找不到这样的整数 x 和 y
1+4=5,1×4=4,所以,加起来等于 5,乘起来等于 4 的二个整数为 1 和 4
7+(-8)=-1,7×(-8)=-56,所以,加起来等于-1,乘起来等于-56 的二个整数为 7 和-8

Input

输入数据为成对出现的整数 n,m(-10000<n,m<10000),它们分别表示整数的和与积,如果两者都为 0,则输入结束。

Output

只需要对于每个 n 和 m,输出“Yes”或者“No”,明确有还是没有这种整数就行了。

Sample Input

9 15
5 4
1 -56
0 0

Sample Output

No
Yes
Yes

解题思路

判断方程:x^2 - nx + m = 0 的 △ 是否为完全平方数

参考源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <cmath>
#include <iostream>
using namespace std;
int main() {
int n, m;
while (cin >> n >> m && (n || m)) {
double delta = n * n - 4 * m;
if (delta >= 0 && delta == (int)sqrt(delta) * (int)sqrt(delta))
cout << "Yes" << endl;
else
cout << "No" << endl;
}
return 0;
}

2093 考试排名

Problem Description

C++编程考试使用的实时提交系统,具有即时获得成绩排名的特点。它的功能是怎么实现的呢?我们做好了题目的解答,提交之后,要么“AC”,要么错误,不管怎样错法,总是给你记上一笔,表明你曾经有过一次错误提交,因而当你一旦提交该题“AC”后,就要与你算一算帐了,总共该题错误提交了几回。虽然你在题数上,大步地跃上了一个台阶,但是在耗时上要摊上你共花去的时间。特别是,曾经有过的错误提交,每次都要摊上一定的单位时间分。这样一来,你在做出的题数上,可能领先别人很多,但是,在做出同样题数的人群中,你可能会在耗时上处于排名的劣势。
例如:某次考试一共 8 题(A,B,C,D,E,F,G,H),每个人做的题都在对应的题号下有个数量标记,负数表示该学生在该题上有过的错误提交次数,但到现在还没有 AC,正数表示 AC 所耗的时间,如果正数 a 跟上一对括号,里面有个整数 b,那就表示该学生提交该题 AC 了,耗去了时间 a,同时,曾经错误提交了 b 次,因此对于下述输入数据:若每次错误提交的罚分为 20 分,则其排名从高到低应该是这样的:
Josephus 5 376
John 4 284
Alice 4 352
Smith 3 167
Bob 2 325
Bush 0 0

Input

输入数据的第一行是考试题数 n(1≤n≤12)以及单位罚分数 m(10≤m≤20),每行数据描述一个学生的用户名(不多于 10 个字符的字串)以及对所有 n 道题的答题现状,其描述采用问题描述中的数量标记的格式,见上面的表格,提交次数总是小于 100,AC 所耗时间总是小于 1000。

Output

将这些学生的考试现状,输出一个实时排名。实时排名显然先按 AC 题数的多少排,多的在前,再按时间分的多少排,少的在前,如果凑巧前两者都相等,则按名字的字典序排,小的在前。每个学生占一行,输出名字(10 个字符宽),做出的题数(2 个字符宽,右对齐)和时间分(4 个字符宽,右对齐)。名字、题数和时间分相互之间有一个空格。

Sample Input

8 20
Smith -1 -16 8 0 0 120 39 0
John 116 -2 11 0 0 82 55(1) 0
Josephus 72(3) 126 10 -3 0 47 21(2) -2
Bush 0 -1 -8 0 0 0 0 0
Alice -2 67(2) 13 -1 0 133 79(1) -1
Bob 0 0 57(5) 0 0 168 -7 0

Sample Output

Josephus 5 376
John 4 284
Alice 4 352
Smith 3 167
Bob 2 325
Bush 0 0

解题思路

因为表格里的数据格式不统一,有时候有"()",有时候又没有,可以使用 sscanf()

参考源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <algorithm>
#include <cmath>
#include <cstring>
#include <iostream>
using namespace std;
struct student {
char name[11];
int ac, time;
};
bool cmp(student a, student b) {
if (a.ac != b.ac)
return a.ac > b.ac;
else if (a.time != b.time)
return a.time < b.time;
else
return a.name < b.name;
}
int main() {
int n, m;
int res, t, f, count = 0;
char s[10];
student stu[1000] = {0};
cin >> n >> m;
for (int i = 0; cin >> stu[i].name; i++) {
count++;
for (int j = 0; j < n; j++) {
cin >> s;
res = sscanf(s, "%d(%d)", &t, &f);
if (res == 2) {
stu[i].ac++;
stu[i].time += t + f * m;
} else if (res == 1 && t > 0) {
stu[i].ac++;
stu[i].time += t;
}
}
}
sort(stu, stu + count, cmp);
for (int i = 0; i < count; i++) {
printf("%-10s %2d %4d\n", stu[i].name, stu[i].ac, stu[i].time);
}
return 0;
}

2094 产生冠军

Problem Description

有一群人,打乒乓球比赛,两两捉对撕杀,每两个人之间最多打一场比赛。球赛的规则如下:如果 A 打败了 B,B 又打败了 C,而 A 与 C 之间没有进行过比赛,那么就认定,A 一定能打败 C。如果 A 打败了 B,B 又打败了 C,而且,C 又打败了 A,那么 A、B、C 三者都不可能成为冠军。根据这个规则,无需循环较量,或许就能确定冠军。你的任务就是面对一群比赛选手,在经过了若干场撕杀之后,确定是否已经实际上产生了冠军。

Input

输入含有一些选手群,每群选手都以一个整数 n(n<1000)开头,后跟 n 对选手的比赛结果,比赛结果以一对选手名字(中间隔一空格)表示,前者战胜后者。如果 n 为 0,则表示输入结束。

Output

对于每个选手群,若你判断出产生了冠军,则在一行中输出“Yes”,否则在一行中输出“No”。

Sample Input

3
Alice Bob
Smith John
Alice Smith
5
a c
c d
d e
b e
a d
0

Sample Output

Yes
No

解题思路

若 a 打败了 b,则将 b 指向 a,若指向空就说明没有人打败他,若这样的人只有一个,则他就是冠军

参考源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <cstring>
#include <iostream>
#include <map>
#include <set>
using namespace std;
int main() {
int n;
string a, b;
set<string> st;
map<string, string> mp;
while (cin >> n && n) {
st.clear();
mp.clear();
for (int i = 0; i < n; i++) {
cin >> a >> b;
st.insert(a);
st.insert(b);
mp[b] = a; // a打败了b
}
int flag = 0;
set<string>::iterator it;
for (it = st.begin(); it != st.end(); it++) {
if (!mp[*it].length()) flag++; //寻找是否有人没被打败
}
if (flag == 1)
cout << "Yes" << endl;
else
cout << "No" << endl;
}
return 0;
}


2095 find your present (2)

Problem Description

In the new year party, everybody will get a “special present”.Now it’s your turn to get your special present, a lot of presents now putting on the desk, and only one of them will be yours.Each present has a card number on it, and your present’s card number will be the one that different from all the others, and you can assume that only one number appear odd times.For example, there are 5 present, and their card numbers are 1, 2, 3, 2, 1.so your present will be the one with the card number of 3, because 3 is the number that different from all the others.

Input

The input file will consist of several cases. Each case will be presented by an integer n (1<=n<1000000, and n is odd) at first. Following that, n positive integers will be given in a line, all integers will smaller than 2^31. These numbers indicate the card numbers of the presents.n = 0 ends the input.

Output

For each case, output an integer in a line, which is the card number of your present.

Sample Input

5
1 1 3 2 2
3
1 2 1
0

Sample Output

3
2

解题思路

题目大意:在新年聚会上,所有人都会收到一份特殊的礼物。选择轮到你领取自己的礼物了。在桌子上有一大堆礼物,其中只有一个是你的。每个礼物上都标有一个号码。而你的礼物的号码是与其他所有礼物都不相同的。你可以假定只有一个数字只出现一次。例如,现在有 5 个礼物,他们分别标号伪 1,2,3,2,1。所以,你的礼物就是标号为 3 的那个。因为 3 只出现了 1 次。

任何数和 0 异或都等于它本身;两个相同的数异或后的结果是 0

参考源码

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <cstdio>
int main() {
int n;
while (scanf("%d", &n) != EOF && n) {
int a, res = 0;
while (n--) {
scanf("%d", &a);
res = res ^ a;
}
printf("%d\n", res);
}
return 0;
}

2096 小明 A+B

Problem Description

小明今年 3 岁了, 现在他已经能够认识 100 以内的非负整数, 并且能够进行 100 以内的非负整数的加法计算.对于大于等于 100 的整数, 小明仅保留该数的最后两位进行计算, 如果计算结果大于等于 100,那么小明也仅保留计算结果的最后两位.例如, 对于小明来说:

  1. 1234 和 34 是相等的
  2. 35+80=15

给定非负整数 A 和 B, 你的任务是代表小明计算出 A+B 的值.

Input

输入数据的第一行为一个正整数 T, 表示测试数据的组数. 然后是 T 组测试数据.每组测试数据包含两个非负整数 A 和 B(A 和 B 均在 int 型可表示的范围内).

Output

对于每组测试数据,输出小明 A+B 的结果.

Sample Input

2
35 80
15 1152

Sample Output

15
67

解题思路

整除

参考源码

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
using namespace std;
int main() {
int t, a, b;
cin >> t;
while (t--) {
cin >> a >> b;
cout << (a % 100 + b % 100) % 100 << endl;
}
return 0;
}

2097 Sky 数

Problem Description

Sky 从小喜欢奇特的东西,而且天生对数字特别敏感,一次偶然的机会,他发现了一个有趣的四位数 2992,这个数,它的十进制数表示,其四位数字之和为 2+9+9+2=22,它的十六进制数 BB0,其四位数字之和也为 22,同时它的十二进制数表示 1894,其四位数字之和也为 22,啊哈,真是巧啊。Sky 非常喜欢这种四位数,由于他的发现,所以这里我们命名其为 Sky 数。但是要判断这样的数还是有点麻烦啊,那么现在请你帮忙来判断任何一个十进制的四位数,是不是 Sky 数吧。

Input

输入含有一些四位正整数,如果为 0,则输入结束。

Output

若 n 为 Sky 数,则输出“#n is a Sky Number.”,否则输出“#n is not a SkyNumber.”。
每个结果占一行。注意:#n 表示所读入的 n 值。

Sample Input

2992
1234
0

Sample Output

2992 is a Sky Number.
1234 is not a Sky Number.

解题思路

进制转换

参考源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
using namespace std;
int sum(int a, int r) { // r进制数各位之和
int s = 0;
while (a) {
s += a % r;
a /= r;
}
return s;
}
int main() {
int n;
while (cin >> n && n) {
if (sum(n, 10) == sum(n, 16) && sum(n, 10) == sum(n, 12))
cout << n << " is a Sky Number." << endl;
else
cout << n << " is not a Sky Number." << endl;
}
return 0;
}

2098 分拆素数和

Problem Description

把一个偶数拆成两个不同素数的和,有几种拆法呢?

Input

输入包含一些正的偶数,其值不会超过 10000,个数不会超过 500,若遇 0,则结束。

Output

对应每个偶数,输出其拆成不同素数的个数,每个结果占一行。

Sample Input

30
26
0

Sample Output

3
2

解题思路

判断素数

参考源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <cmath>
#include <iostream>
using namespace std;
bool isPrime(int a) {
if (a == 2 || a == 3) return 1;
for (int i = 2; i <= sqrt(a); i++) {
if (a % i == 0) return false;
}
return true;
}
int main() {
int n, count;
while (cin >> n && n) {
count = 0;
for (int i = 2; i < n / 2; i++) {
if (isPrime(i) && isPrime(n - i)) count++;
}
cout << count << endl;
}
return 0;
}

2099 整除的尾数

Problem Description

一个整数,只知道前几位,不知道末二位,被另一个整数除尽了,那么该数的末二位该是什么呢?

Input

输入数据有若干组,每组数据包含二个整数 a,b(0<a<10000, 10<b<100),若遇到 0 0 则处理结束。

Output

对应每组数据,将满足条件的所有尾数在一行内输出,格式见样本输出。同组数据的输出,其每个尾数之间空一格,行末没有空格。

Sample Input

200 40
1992 95
0 0

Sample Output

00 40 80
15

解题思路

前数*100+尾数

参考源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
using namespace std;
int main() {
int a, b;
while (cin >> a >> b && (a || b)) {
int count = 0;
for (int i = 0; i < 100; i++) {
if ((a * 100 + i) % b == 0) {
count++;
if (count == 1)
printf("%02d", i);
else
printf(" %02d", i);
}
}
cout << endl;
}
return 0;
}

相关内容