星球杯实验室2022.10.18作业题题解

A:题目 1008: 

[编程入门]成绩评定

#include <stdio.h>
int main(){
    int score;
    scanf("%d",&score);
    if(score>=90) printf("A");
    else if(score>=80) printf("B");
    else if(score>=70) printf("C");
    else if(score>=60) printf("D");
    else printf("E");
}

本题考查简单的分支,只需按照题意写if,else即可


B:题目 1010: 

[编程入门]利润计算

#include <stdio.h>
int main(){
    int l;
    scanf("%d",&l);
    int bonus;
    if(l<=100000) bonus=l*0.1;
    else if(l<=200000) bonus=10000+(l-100000)*0.075;
    else if(l<=400000) bonus=17500+(l-200000)*0.05;
    else if(l<=600000) bonus=27500+(l-400000)*0.03;
    else if(l<=1000000) bonus=33500+(l-600000)*0.015;
    else bonus=39500+(l-1000000)*0.01;
    printf("%d",bonus);
}

依旧考查分支的知识点,本题其实只是一个分段函数,由于题目要求输出和输出都是整数,所以也无需用浮点型定义变量。


C:题目 1141: 

C语言训练-百钱百鸡问题

#include <stdio.h>
int main(){
    for(int i=0;i<=20;i++){
        for(int j=0;j<=34;j++){
            for(int k=0;k<=100;k+=3){
                if(i+j+k==100 && 5*i+3*j+k/3==100){
                    printf("cock=%d,hen=%d,chicken=%d\n",i,j,k);
                }
            }
        }
    }
}

方法一,最简单直白的三元一次方程穷举法,三层的循环嵌套,很简单可以得到我们想要的答案。

#include <stdio.h>
int main(){
    for(int i=0;i<=20;i++){
        for(int j=0;j<=34;j++){
            int k=100-i-j;
            if(i*5+j*3+k/3==100 && k%3==0) printf("cock=%d,hen=%d,chicken=%d\n",i,j,k);
        }
    }
}

方法二,在方法一的基础上减少了一层循环的嵌套,优化了算法

PS.你能在方法二的基础上继续优化吗(三元一次方程组,有一个已知量和两个方程式,求剩下的两个未知量,思考后可以尝试自己写一写,如果想不出来可以去看这个题解:百(N)钱百(N)鸡问题【四层解法递进】-题解(C++代码)-Dotcpp编程社区


D:题目 1018: 

[编程入门]有规律的数列求和

#include <stdio.h>
int main(){
    float sum=0.0;
    float i=2,j=1,temp;
    int n;
    scanf("%d",&n);
    for(int r=0;r<n;r++){
        sum+=i/j;
        temp=i;
        i+=j;
        j=temp;
    }
    printf("%.2f",sum);
    return 0;
}

题解:本题需要找规律,会发现每个分数的分子是前一个数的分子分母和,分母是前一个数的分子,所以我们需要单独定义一个temp变量来当做中间变量存放变之前的i,这里i和j我们也用浮点型定义,因为如果是整形的话,下面的循环里,sum会被类型转换,导致最后结果错误。


E:题目 1022: 

[编程入门]筛选N以内的素数

#include <stdio.h>
#include <math.h>
int main(){
    int n;
    scanf("%d",&n);
    for(int i=2;i<=n;i++){
        int isprime=1;//用于记录是否是素数
        for(int j=sqrt(i);j>=2;j--){
            if(i%j==0){
                isprime=0;
                break;
            }
        }
        if(isprime) printf("%d\n",i);//如果是素数的话就输出
    }
}

 最简单的暴力算法,两层循环的嵌套,但我们只需要判断2到i的平方根内有没有能被i整除的数即可判断i是否是一个素数(本题也可以优化(欧拉筛),但需要用到数组,故不在此赘述)


F:题目 2692: 

蓝桥杯2022年第十三届省赛真题-质因数个数

面对这题,可能大部分的思路首先还是简单粗暴的暴力算法,用两层循环判断素数,然后再判断这个素数是否是n的约数,提交,然后会发现,时间超限,这可能是各位同学第一次遇见会时间超限的题吧,那么我们就需要优化算法。首先我们可能会想到,先判断这个数是不是n的约数,再判断这个数是不是素数,可能会好一点,确实相比较于前一个方法,会好很多,但是还是会超时。那么最优解是什么样的呢,最优解用到了欧拉筛的思想。

#include <stdio.h>
int main(){
    long long int n,ans=0;
    scanf("%ld",&n);
    for(long long int i=2;i<=n/i;i++){
        if(n%i==0){
            ans++;
            while(n%i==0) n/=i;
        }
    }
    if(n>1) ans++;
    printf("%ld",ans);
}

 我们知道,任何合数都一定有比这个数小的质因数,所以我们从2开始,每遇见一个能整除n的i,就令n循环除等于i,这样就可以排除所有以质数i为因数的n的合数因数(多读几遍),此时,当我们在循环中再次遇见可以整除n(此时n已经循环除尽前一个i)的i,这个i就一定是质数。

那么,为什么在for循环里的限制条件是i<=n/i呢,我们假设一个j,令i*j=n,那么j就等于n/i,当i>j时,因式的形式就只是当i<=j时的乘法交换律变形罢了,所以我们只需判断在i<=j范围内,有无能整除n的因子i, 所以限制条件便是i<=n/i

最后,为什么当n>1时ans++,当循环结束后,已经排除了n的所有合数因数,此时的n本身就是原n的一个因数(一开始输入的n)只要n>1,那么这个n就绝对是原n的一个质数因数,所以此时ans++

感兴趣的同学可以去搜索欧拉筛,并了解一下

本题可以把代码复制到自己的编译器上,自己设置断点debug一下,有助于理解 


G:题目 2701: 

蓝桥杯2022年第十三届决赛真题-取模(C/C++/Java组)

#include <stdio.h>
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int n,m,judge=0;
        scanf("%d %d",&n,&m);
        for(int y=1;y<=m;y++){
            for(int x=1;x<y;x++){
                if(n%x==n%y){
                    judge=1;
                    break;
                }
            }
            if(judge==1) break;
        }
        if(judge)printf("Yes\n");
        else printf("No\n");
    }
}

 这题竟然暴力就可以做出来(没错我也很震惊)但需要注意,如果外层循环是x,内层循环是y的话,照样还是过不了的,judge=1时,还要跳出函数,否则还是会超时,在暴力的基础上简单优化,这题就可以过。

以下是由江夏学长友情赞助的本题最优解(毕竟感觉这题不应该用暴力解法不卡时间复杂度),运用了中国剩余定理,感兴趣的同学可以研究一下

#include<stdio.h>

void solve(){
    int n, m; scanf("%d %d", &n, &m);
    int is = 0;
    m = m > 13? 13:m;
    for(int i=2; i<=m; i++){
        if( n%i != i-1){
            is = 1;
            break;
        }
    }
    if(is) printf("Yes\n");
    else printf("No\n");
}

int main(){
    int t; scanf("%d", &t);
    while(t--) solve();
    return 0;
}

中国剩余定理(孙子定理)_~ 知至~的博客-CSDN博客_中国剩余定理

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值