C语言流程控制的几道题目总结

输出[a,b]内的所有完数

方式一

#include<stdio.h>

void Judge(int a,int b){
    int i,j,t;
    for(i=a;i<=b;i++){//遍历[1,b]内的每个数,找因子
        t = 1;
        for(j=2;j<i;j++){//找因子
            if(i%j == 0) t+=j;   
        }
        if(t == i && t>a) printf("%d\n",t); 
    }
}
int main(void){
    int a,b;
    scanf("%d %d",&a, &b);
    Judge(a,b);
    return 0;
}

方式二

#include<stdio.h>

int function( int n );

int main(void){
    int a, b, i;
    scanf( "%d %d", &a, &b );
    for( i = a; i <= b; i++ ){
        if( function(i) == 1){
            printf( "%d\n", i);
        }
    }
    return 0;
}

int function( int n ){
    int i, sum = 0;
    if( n == 1) return 0;
    for( i = 2; i < n; i++ ){
        if( n % i == 0){
            sum += i;
        }
    }
    if ( sum + 1 == n ) return 1;
    return 0;
}

前一种方式是第一次做这个题目时写的,第二种方式是复习的时候重新写的,代码风格还是变化了一丢丢hhh。

最大公约数

方式一

#include<stdio.h>

  void gcd(int a, int b){
      int i,j,max=1;
      if(!a){//a=0
          if(b == 1) 
             max = 1;
          else//b不为1
             max = b;
      }
      else if(!b){//b=0
          if(a == 1) 
             max = 1;
          else//a不为1
             max = a;
      }
      else{//a,b均不为1,0
          if(a<b){
              for(i=2;i<=a;i++){
              if(a%i == 0 && b%i == 0) max = i;
              }
            }
          else{
              for(i=2;i<=b;i++){
              if(a%i == 0 && b%i == 0) max = i;
              }
          }
      }
       printf("%d\n",max);
  }
 int main(void){
     int a,b;
     scanf("%d %d", &a, &b);
     gcd(a,b);
     return 0;
 }

方式二

#include<stdio.h>

int main( void ){
    int m, n, r;
    scanf( "%d %d", &m, &n );
    r = m % n;
    while( r ){
        m = n;
        n = r;
        r = m % n;
    }
    printf( "%d\n" , n );
    return 0;
}

方式二是在初步了解算法之后学到的,辗转相除法。方式一是百度的定义然后从定义出发分类讨论写的。

角谷定理验证

#include<stdio.h>

int main( void ){
    int n,count = 0;
    scanf( "%d\n", &n );
    while( n != 1){
        if( n %2 == 0){
            n = n /2;
            count++;
        }
        if( n % 2 !=0 ){
            n = 3 * n + 1;
            count++;
        }
    }
    printf( "%d\n", count);
    return 0;
}

代码还可以再简洁一点,把n % 2 != 0简化为!( n % 2 )等。

验证哥德巴赫猜想

方式一

#include<stdio.h>
int Isright(int n){
    int i;
    for(i=2;i<n/2;i++){
        if(n%i == 0) return 0;//是
    }
    return 1;
}

int main(void){
    int n,i,k=0,a[10],j=0;
    scanf("%d\n",&n);
    if(!(n%2)){
        for(i=2;i<n/2;i++){
            k = n - i;
            if(Isright(k)&&Isright(i)) a[j++]=i;
      }
    }
    printf("%d %d\n",a[0], n-a[0]);
    return 0;
}

方式二

#include<stdio.h>
#include<math.h>

int prime( int n );

int main( void ){
    int n,i;
    scanf( "%d", &n);
    if( n % 2 == 0 ){
        for( i = 2; i < n ; i++ ){
            if( prime(i) && prime(n-i)){
                printf( "%d %d\n", i, n-i);
                break;
            }
        }
    }
    return 0;
}

int prime( int n){
    int i,sqr;
    if( n < 1) return 0;
    sqr = (int)sqrt( 1.0 * n );
    for( i = 2; i <= sqr; i++ ){
        if( n % i == 0 ) return 0;
    }
    return 1;
}

其实重点在于定义一个判断素数的函数,(素数判断也是C语言流程控制里一个比较经典的题目),有多种定义方式,看自己喜好。方式一是我自己根据定义写的,OJ上是过了的,但是也有可能存在一些边界或者是其他的什么问题没有考虑到,方式二应该算是一种比较经典的判断素数的函数(从算法书上看到的),比较简洁。把判断条件sqr单独拎出来在循环之前定义,减少了sqr的运算次数,在n比较大的时候优点比较明显。如果放在循环条件里,每一次循环都要计算一次sqr,就比较繁琐。

折点计数

#include<stdio.h>

int main( void ){
    int n, i, count = 0;
    scanf( "%d\n", &n );
    int a[n];
    for( i = 0; i < n; i++ ){
        scanf( "%d ", &a[i]);
    }

    for( i = 1; i < n - 1; i++ ){
        if( a[i-1] < a[i] && a[i+1] < a[i] ){
            count++;
        }
        if( a[i-1] > a[i] && a[i+1] > a[i] ){
            count++;
        }
    }
    printf( "%d\n", count);
    return 0;
}

还是要从折点的定义出发,难点应该是在边界控制上,数组下标从0开始,n-1结束,判断需要涉及三个点,那么i应该从1开始,取到n-1-1结束,即i<n-1,左右边界判断好即可。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值