入门模拟不涉及算法知识,题目都比较简单。多多练习,多敲代码即可。
3.1 简单模拟
模拟题是一类“题目怎么说,你就怎么做”的题目,实现起来简单的就称之为“简单模拟”。它不涉及算法,考验的是代码能力。
题目描述:
卡拉兹(Callatz)猜想:
对任何一个自然数 n n n,如果它是偶数,那么就把它砍掉一半;如果它是奇数,那么把( 3 n + 1 3n+1 3n+1)砍掉一半。这样一直反复砍下去,最后一定在某一步得到 n = 1 n=1 n=1。卡拉兹在1950年的世界数学家大会上公布了这个猜想,传说当时耶鲁大学师生齐动员,拼命想证明这个貌似很荒唐……
此处并非要证明卡拉兹猜想,而是对给定的任一不超过1000的正整数 n n n,简单地数一下,需要多少步才能得到 n = 1 n=1 n=1?
输入格式:
每个测试输入包含1个测试用例,即给出自然数 n n n的值。
输出格式:
输出从 n n n计算到1需要的步数
输入样例:
3
输出样例:
5
思路:
简单模拟基本都是题目怎么说我们就怎么做。所以我们可以用一个循环,当 n n n不等于1的时候就进入调整,等于1的时候就输出计算的步数。调整的方式就跟题目说的一样,当 n n n为偶数,砍去一半;为奇数,砍去 ( 3 n + 1 ) (3n+1) (3n+1)的一半。
我们这里简单看一下样例是怎么操作得到的。首先输入样例为3,是奇数,调整为 ( 3 ∗ 3 + 1 ) / 2 = 5 (3*3+1)/2=5 (3∗3+1)/2=5;5为奇数,调整为 ( 3 ∗ 5 + 1 ) / 2 = 8 (3*5+1)/2=8 (3∗5+1)/2=8;8为偶数,调整为 8 / 2 = 4 8/2=4 8/2=4;4为偶数,调整为 4 / 2 = 2 4/2=2 4/2=2;2为偶数,调整为 2 / 2 = 1 2/2=1 2/2=1。此时 n n n被调整为了1,于是我们要停止对数字的调整,然后数一数我们一共调整了几次。很明显是5次,输出样例也就是这么来的。
参考代码:
#include <cstdio>
int main(){
// n表示自然数,step表示计算次数也即步数
int n, step=0;
// 读入自然数
scanf("%d", &n);
// 当n还不等于1的时候,进去砍他
while(n != 1){
// 如果n为偶数,将它本身砍去一半
if(n % 2 == 0){
n = n / 2;
// 如果n为奇数,就将(3*n+1)砍去一半
}else{
n = (3*n+1) / 2;
}
// 计数
step++;
}
// 当n等于1或者被调整为1后,输出步数。
printf("%d\n", step);
return 0;
}
题目描述:
为了用事实说明挖掘机技术到底哪家强,PAT组织了一场挖掘机技能大赛。请根据比赛结果统计出技术最强的那个学校。
输入格式:
在第1行给出不超过105的正整数N,即参赛人数。随后N行,每行给出一位参赛者的信息和成绩,包括其所代表的学校的编号(从1开始连续编号)及其比赛成绩(百分制),中间以空格分隔。
输出格式:
在一行中给出总得分最高的学校的编号及其从分,中间以空格分隔。题目保证答案唯一,没有并列。
输入样例:
6
3 65
2 80
1 100
2 70
3 40
3 0
输出样例:
2 150
思路:
- 这里的编号对应分数很容易让我们想到数组。数组的下标可以用来指示学校的编号,数组的值可以用来表示学校的分数。由于一个学校会有多个参赛人员,即每个学校有多个分数,而我们求得是其总分,所以为了方便,我们可以在读入数据时直接计算每个学校的总分。
- 这里的学校编号是从1开始连续编号,所以我们可以直接循环枚举每一个编号的总分,最后找出最高的总分及其编号。
我们这里简单看一下样例是如何操作的。第一行的6表示一共有6个参赛者,那么读入参赛者数据的时候,我们循环6次即可。从第2行开始,我们可以用一个数组school来记录总分,3 65
表示编号为3的学校有人获得65分,于是我们定义school[3]=65,即编号为3的学校现在的总分为65。同理,有school[2]=80,school[1]=100。到第五行时,编号为2的学校有人又得到了一个分数70,由于我们要求的是总分,所以school[2]=80+70=150,即编号为2的学校现在总分为150。接下来的操作也类似,最终有school[1]=100、school[2]=150、school[3]=105。很明显,最高的总分的学校编号为2,最高的总分为150。
参考代码:
#include <cstdio>
// 第一行的正整数最大为100000,
// 我们一般将其定义的更大一些,保证数组不会出错
const int maxn = 100010;
// 将所有学校的总分初始化为0
int school[maxn] = {0};
int main(){
// 参赛人数n
int n;
scanf("%d", &n);
// 读入学校编号info和分数score
int info, score;
// 参赛人员为n,所以我们只需循环n次
for(int i=0; i<n; i++){
scanf("%d%d", &info, &score);
// 一边读入数据,我们一边计算每个学校的总分
school[info] += score;
}
// 最高的总分maxScore和对应的学校编号maxNum
int maxNum=1, maxScore=-1;
// 使用一个循环遍历所有学校的总分,找出最高的
for(int i=1; i<=n; i++){
// 如果当前学校的总分大于现有最高的总分
if(school[i] > maxScore){
// 将当前学校的编号赋值给maxNum
maxNum = i;
// 将当前学校的总分赋值给maxScore
maxScore = school[i];
}
}
// 输出最高总分的学校编号及其总分
printf("%d %d\n", maxNum, maxScore);
return 0;
}