B - 求平均成绩
假设一个班有n(n<=50)个学生,每人考m(m<=5)门课,求每个学生的平均成绩和每门课的平均成绩,并输出各科成绩均大于等于平均成绩的学生数量。
Input
输入数据有多个测试实例,每个测试实例的第一行包括两个整数n和m,分别表示学生数和课程数。然后是n行数据,每行包括m个整数(即:考试分数)。
Output
对于每个测试实例,输出3行数据,第一行包含n个数据,表示n个学生的平均成绩,结果保留两位小数;第二行包含m个数据,表示m门课的平均成绩,结果保留两位小数;第三行是一个整数,表示该班级中各科成绩均大于等于平均成绩的学生数量。
每个测试实例后面跟一个空行。Sample Input
2 2 5 10 10 20Sample Output
7.50 15.00 7.50 15.00 1
思路:累加计算即可,但注意,先进行除法再累加会出现精度问题。
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 100, MAXM = 10;
int score[MAXN][MAXM]; //存储学生的成绩
double StuAve[MAXN], ClaAve[MAXM]; //学生的平均成绩 每个科目的平均成绩
int main() {
int n, m;
while (scanf("%d %d", &n, &m) != EOF) {
memset(StuAve, 0, sizeof(StuAve));
memset(ClaAve, 0, sizeof(ClaAve));
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
scanf("%d", &score[i][j]); //累加每个学生对平均成绩的贡献
StuAve[i] += score[i][j];
ClaAve[j] += score[i][j];
}
StuAve[i] /= m;
}
for (int i = 0; i < m; i++)
ClaAve[i] /= n;
int cnt = 0; //各科成绩均大于等于平均成绩的学生数量
for (int i = 0; i < n; i++) {
bool flag = true;
for (int j = 0; j < m; j++) {
if (score[i][j] < ClaAve[j]) {
flag = false;
break;
}
}
cnt += flag;
}
printf("%.2f", StuAve[0]);
for (int i = 1; i < n; i++) printf(" %.2f", StuAve[i]);
printf("\n%.2f", ClaAve[0]);
for (int i = 1; i < m; i++)
printf(" %.2f", ClaAve[i]);
putchar('\n');
printf("%d\n\n", cnt);
}
}
C - 母牛的故事
有一头母牛,它每年年初生一头小母牛。每头小母牛从第四个年头开始,每年年初也生一头小母牛。请编程实现在第n年的时候,共有多少头母牛?
Input
输入数据由多个测试实例组成,每个测试实例占一行,包括一个整数n(0<n<55),n的含义如题目中描述。
n=0表示输入数据的结束,不做处理。Output
对于每个测试实例,输出在第n年的时候母牛的数量。
每个输出占一行。Sample Input
2 4 5 0Sample Output
2 4 6
思路: 假设用f[i]代表第i年母牛的数量,那么可得递推式—— f[i] = f[i-1] + f[i-3] ( i≥4) 。即这一年母牛的数量 = 原来的牛的数量 + 新增的牛的数量。原来牛的数量就是去年牛的数量。三年前的所有牛到这一年的年龄都超过四年,都可以产生新的小牛,并且从这一年到三年前产生的牛都不到四年,不能生小牛,所以,新增的牛的数量就是三年前牛的数量。
#include <iostream>
using namespace std;
const int MAXN = 60;
int f[MAXN];
void Init() {
f[0] = 0, f[1] = 1, f[2] = 2, f[3] = 3;
for (int i = 4; i < MAXN; i++) f[i] = f[i - 1] + f[i - 3];
}
int main() {
Init();
int n;
while (cin >> n && n) {
cout << f[n] << endl;
}
}
F - 发工资咯:)
作为杭电的老师,最盼望的日子就是每月的8号了,因为这一天是发工资的日子,养家糊口就靠它了,呵呵
但是对于学校财务处的工作人员来说,这一天则是很忙碌的一天,财务处的小胡老师最近就在考虑一个问题:如果每个老师的工资额都知道,最少需要准备多少张人民币,才能在给每位老师发工资的时候都不用老师找零呢?
这里假设老师的工资都是正整数,单位元,人民币一共有100元、50元、10元、5元、2元和1元六种。Input
输入数据包含多个测试实例,每个测试实例的第一行是一个整数n(n<100),表示老师的人数,然后是n个老师的工资。
n=0表示输入的结束,不做处理。Output
对于每个测试实例输出一个整数x,表示至少需要准备的人民币张数。每个输出占一行。
Sample Input
3 1 2 3 0Sample Output
4
思路: 优先用大额的钱即可保证数量最少
#include <iostream>
using namespace std;
const int money[] = {100, 50, 10, 5, 2, 1};
int getNum(int x) {
int cnt = 0;
for (int i = 0; x && i < 6; i++) {
cnt += (x / money[i]);
x %= money[i];
}
return cnt;
}
int main() {
int n;
while (cin >> n && n) {
int cnt = 0, temp;
for (int i = 0; i < n; i++) {
cin >> temp;
cnt += getNum(temp);
}
cout << cnt << endl;
}
return 0;
}
G - C语言合法标识符
输入一个字符串,判断其是否是C的合法标识符。
Input
输入数据包含多个测试实例,数据的第一行是一个整数n,表示测试实例的个数,然后是n行输入数据,每行是一个长度不超过50的字符串。
Output
对于每组输入数据,输出一行。如果输入数据是C的合法标识符,则输出"yes",否则,输出“no”。
Sample Input
3 12ajf fi8x_a ff ai_2Sample Output
no yes no
思路: 按照标识符规则判断即可。字母或下划线开头,由字母数字下划线组成。
#include <iostream>
#include <string>
using namespace std;
int main() {
int T;
cin >> T;
getchar();
string temp;
while (T--) {
getline(cin, temp);
if (!(isalpha(temp[0]) || temp[0] == '_')) {
cout << "no" << endl;
continue;
}
int tlen = (int)temp.length();
bool flag = true;
for (int i = 1; i < tlen; i++) {
if (!(isalnum(temp[i]) || isalpha(temp[i]) || temp[i] == '_')) {
flag = false;
break;
}
}
cout << (flag ? "yes" : "no") << endl;
}
return 0;
}
H - 首字母变大写
#include <iostream>
#include <string>
using namespace std;
int main() {
string temp;
while (getline(cin, temp)) {
int len = (int)temp.length();
bool flag = true;
for (int i = 0; i < len; i++) {
if (temp[i] == ' ') {
flag = true;
} else if (flag) {
if ('a' <= temp[i] && temp[i] <= 'z') temp[i] += ('A' - 'a');
flag = false;
}
}
cout << temp << endl;
}
return 0;
}
I - Doggo Recoloring
题意:有n个小狗,每一种小写字母代表一种颜色,然后颜色的个数在两个以上的就可以染成别的任意颜色,操作次数不限,问你最后能不能把所有的小狗染成同一种颜色。
思路:两个以上的就可以变成其他颜色,那么只要有一种颜色的数量在两个以上,那么就可以顺次变成其他所有的颜色,然后统一起来,所以,最终颜色不能统一的情况,就只有每个颜色只有一个的情况。所以只需要判断存不存在颜色的个数大于两个就ok
#include <cstdio>
using namespace std;
const int MAXN = (int)1e5 + 10;
char s[MAXN];
int vis[300];
int main() {
int n;
scanf("%d %s", &n, s);
for (int i = 0; i < n; i++) {
if (vis[s[i]]) {
printf("Yes\n");
return 0;
}
vis[s[i]] = 1;
}
printf(n == 1 ? "Yes\n" : "No\n");
return 0;
}
J - Sonya and Exhibition
题意:有一排n个格子,每个格子里能放一种花,一共有两种花,一种用 0 代表,另一种用 1 代表,然后给你m各区间,每个区间的价值就是这个区间内的两种花的数量之积。问你应该怎么放花,使得这些区间的价值和最大。
思路:题目的意思转化一下,就是说让0 1 的个数在各个区间内都是接近的(和相等,越接近,积越大),也就是说0 1 分布均匀,那么,我们直接0 1 交替输出,就可以保证0 1 在各个区间都是最接近的。
#include <cstdio>
using namespace std;
int main() {
int n, m;
scanf("%d%d", &n, &m);
int l, r;
for (int i = 1; i <= m; i++) scanf("%d%d", &l, &r);
for (int i = 0; i < n; i++) printf("%d", i % 2);
putchar('\n');
return 0;
}
K - Find Extra One
题意: 问你在二维平面上,去除掉一个点后,剩下的点是否在y轴的同侧。
思路:判断在y轴左边(或者右边)的点是不是只有一个或者是零个即可。
#include <iostream>
using namespace std;
int main() {
int n, tx, ty;
while (cin >> n) {
int cnt1 = 0, cnt2 = 0;
for (int i = 0; i < n; i++) {
cin >> tx >> ty;
tx < 0 ? cnt1++ : cnt2++;
}
cout << ((cnt1 == 1 || cnt2 == 1 || cnt1 == 0 || cnt2 == 0) ? "Yes\n" : "No\n");
}
return 0;
}
L - Visiting a Friend
题意: Pig家在0点处,他的朋友家在m处,现在又一些传送带,每条传送带可以从起点传送到起点至终点之间的任意一点,问Pig能否通过传送带到达朋友家。
思路:我们发现Pig能达到他的朋友家其实就是传送带覆盖了0~m的整个区间,那么问题就等价为了这些传送带是否能覆盖这一整个区间。因为给出区间的起点是有序的,所以我们只需要维护一个能到达的最远的点,每次判断能否进行下次传送,如果可以,就尝试更新能到达的最远的点,最后判断能否到达m点即可。
#include <algorithm>
#include <iostream>
using namespace std;
int main() {
int n, m;
while (cin >> n >> m) {
int cnt = 0, ta, tb;
for (int i = 0; i < n; i++) {
cin >> ta >> tb;
if (cnt >= ta) cnt = max(cnt, tb);
}
cout << (cnt >= m ? "YES\n" : "NO\n");
}
return 0;
}
M - Vicious Keyboard
题意:有一个只由‘V’和‘K’组成的字符串,你最多可以更改一个字符,问字符串中最多有多少个‘VK’。
思路: 统计字符串中有多少个VK,然后再看字符串中是否还存在‘VV’或者‘KK’,如果有就让答案+1。注意这里的vv,kk中的vk不能是第一次找到的组成vk的v或者k。
#include <iostream>
#include <string>
using namespace std;
int main() {
string temp;
cin >> temp;
int len = (int)temp.length(), ans = 0;
for (int i = 0; i < len - 1; i++) {
if (temp[i] == 'V' && temp[i + 1] == 'K') {
ans++;
temp[i] = temp[i + 1] = '*';
}
}
for (int i = 0; i < len - 1; i++) {
if ((temp[i] == 'V' && temp[i + 1] == 'V') ||
(temp[i] == 'K' && temp[i + 1] == 'K')) {
ans++;
break;
}
}
cout << ans << endl;
return 0;
}
N - Heidi and Library (easy)
题意: 有n本书籍,编号从1到n。有一个图书馆,一开始这个图书馆是空的。在连续的n天里,每天都会有人来借走一本书,然后在晚上归还,如果图书馆里没有这本书的话,图书馆的人就会去购买这本书(所有书的价格都是1)来方便人借阅,但是图书馆最多只能容纳k本书,如果超过k本,就需要丢弃一本来腾出空间。问图书馆满足所有人要求的最低花费是多少?
思路:对于每天需要借的书,如果图书馆里有的话,就直接不用管了,如果图书馆里没有的话并且图书馆还没满的话,直接购买需要的图书即可,所以,问题就是需要舍弃图书的时候应该怎么舍弃。显然可以知道应该舍弃下一次出现时间最靠后的那本书,这样是最优的(因为这本书闲置占用图书馆的时间最长)。
#include <cstring>
#include <iostream>
#include <queue>
#include <set>
using namespace std;
const int MAXN = 100;
int a[MAXN];
int main() {
int n, k, ans = 0;
cin >> n >> k;
for (int i = 0; i < n; i++) cin >> a[i];
set<int> s, ts;
for (int i = 0; i < n; i++) {
if (s.find(a[i]) == s.end()) {
ans++;
if (s.size() >= k) {
ts = s;
for (int j = i + 1; j < n && ts.size() > 1; j++) ts.erase(a[j]);
s.erase(*ts.begin());
}
s.insert(a[i]);
}
}
cout << ans << endl;
return 0;
}
自己的提交看不了,所以只好整改一下题解了……不过赵神的题解我绝对得给一万个赞!超级详细且通俗易懂!(献花!)