算法协会寒假训练One

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 20

Sample 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
0

Sample 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
0

Sample 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_2

Sample 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;
}

自己的提交看不了,所以只好整改一下题解了……不过赵神的题解我绝对得给一万个赞!超级详细且通俗易懂!(献花!)

      

 

 

 

 

 

    

      

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值