《算法笔记》笔记之笔记 - 3、入门模拟(1) - 简单模拟

16 篇文章 0 订阅
16 篇文章 0 订阅

入门模拟不涉及算法知识,题目都比较简单。多多练习,多敲代码即可。

3.1 简单模拟

模拟题是一类“题目怎么说,你就怎么做”的题目,实现起来简单的就称之为“简单模拟”。它不涉及算法,考验的是代码能力。

【PAT B1001】害死人不偿命的(3n+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 (33+1)/2=5;5为奇数,调整为 ( 3 ∗ 5 + 1 ) / 2 = 8 (3*5+1)/2=8 (35+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 B1032】挖掘机技术哪家强

题目描述:

为了用事实说明挖掘机技术到底哪家强,PAT组织了一场挖掘机技能大赛。请根据比赛结果统计出技术最强的那个学校。

输入格式:

在第1行给出不超过105的正整数N,即参赛人数。随后N行,每行给出一位参赛者的信息和成绩,包括其所代表的学校的编号(从1开始连续编号)及其比赛成绩(百分制),中间以空格分隔。

输出格式:

在一行中给出总得分最高的学校的编号及其从分,中间以空格分隔。题目保证答案唯一,没有并列。

输入样例:

6

3 65

2 80

1 100

2 70

3 40

3 0

输出样例:

2 150

思路:

  1. 这里的编号对应分数很容易让我们想到数组。数组的下标可以用来指示学校的编号,数组的值可以用来表示学校的分数。由于一个学校会有多个参赛人员,即每个学校有多个分数,而我们求得是其总分,所以为了方便,我们可以在读入数据时直接计算每个学校的总分。
  2. 这里的学校编号是从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;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值