杭电OJ第11页2000-2009道题(C语言)

1. ASCII码排序

问题描述

输入三个字符后,按各字符的ASCII码从小到大的顺序输出这三个字符

Input:
输入数据有多组,每组占一行,有三个字符组成,之间无空格

Output:
对于每组输入数据,输出一行,字符中间用一个空格分开

Sample:
输入:qwe
      asd
      zxc
输出:e w q
      a d s
      c x z

解题思路

字符,是以ascall码的形式储存的;跟整型数据是一样的;
字符之间可以进行运算,本质上是ascall码值的比较;
问题转化为三个数的排序问题
扩展:小写字母比大写字母的ascall值大32

代码

# include <stdio.h>

int main()
{
    char a, b, c, t;
    while(scanf("%c%c%c", &a,&b,&c) == 3)
    {
        char temp = getchar();  //重点地方,getchar吸收回车符(getchar函数从控制台中读取字符,直到按回车结束)
        printf("%c\n", temp);
        if(a > b)   {t = a;a = b;b = t;} //必有a <= b
        if(a > c)   {t = a;a = c;c = t;} //必有a <= c
        if(b > c)   {t = b;b = c;c = t;} //必有b <= c

        //a <= b <= c
        printf("%c %c %c\n", a, b, c);
    }

    return 0;
}

重点

getchar函数

读取标准输入的一个字符,直到按回车(识别到'\n')为止
如果输入多个字符,其他字符会被放在缓存区,等待后续getchar调用
返回值:相应字符的ascall值

scanf返回值的问题

  1. 正确输入参数的个数
  2. EOF,输入流已经结束。在Windows下,用户按下CTRL+Z(会看到一个^Z字符)再按下回车,就表示输入结束;Linux/Unix下使用CTRL+D表示输入结束。

2. 计算两点间的距离

问题描述

输入两点坐标(x1, y1), (x2, y2)

input:
输入数据有多组,每组占一行,由4个实数组成,分别表示x1, y1, x2, y2,数据之间用空格隔开。

output:
对于每组输入数据,输出一行,结果保留两位小数。

解题思路

欧式距离公式

代码

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


int main()
{
    double x1, y1, x2, y2, dist;
    while(scanf("%lf %lf %lf %lf", &x1, &y1, &x2, &y2) == 4)
    {
        getchar();
        dist = sqrt(pow((x1 - x2), 2) + pow((y1 - y2), 2));

        printf("%.2f\n", dist);
    }


    return 0;
}

重点

scanf的输入问题

  1. 输入,数据之间用空格隔开
  2. double类型输入必须使用%lf才能得到正确的值;输出可以使用%f

3. 计算球的体积

问题描述

Problem Description
根据输入的半径值,计算球的体积。
 

Input
输入数据有多组,每组占一行,每行包括一个实数,表示球的半径。
 

Output
输出对应的球的体积,对于每组输入数据,输出一行,计算结果保留三位小数。
 

Sample Input
1
1.5
 

Sample Output
4.189
14.137

Hint

#define PI 3.1415927

解题思路

v = 3/4 * pi * pow(r, 3)

代码

#include <stdio.h>
#include <math.h>
#define PI 3.1415927

int main()
{
    double r, v;
    while(scanf("%lf", &r) == 1)
    {
        v = 4/3.0 * PI * pow(r, 3); //乘法和除法优先级相同
        printf("%.3f\n", v);
    }

    return 0;
}

重点

注意

必须是 4/3.0 → 1.33

如果是 4/3 → 1.00。最后答案也不对了

4. 求绝对值

问题描述

Problem Description
求实数的绝对值。
 

Input
输入数据有多组,每组占一行,每行包含一个实数。
 

Output
对于每组输入数据,输出它的绝对值,要求每组数据输出一行,结果保留两位小数。
 

Sample Input
123
-234.00
 

Sample Output
123.00
234.00

解题思路

#include <math.h>中的fabs()函数

代码

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


int main()
{
    double x;
    while(scanf("%lf", &x) == 1)
    {
        printf("%.2f\n", fabs(x));
    }

    return 0;
}

重点

<stdlib.h>中的abs(x),x只能是长整型

5. 成绩转换

问题描述

Problem Description
输入一个百分制的成绩t,将其转换成对应的等级,具体转换规则如下:
90~100为A;
80~89为B;
70~79为C;
60~69为D;
0~59为E;
 

Input
输入数据有多组,每组占一行,由一个整数组成。
 

Output
对于每组输入数据,输出一行。如果输入数据不在0~100范围内,请输出一行:“Score is error!”。
 

Sample Input
56
67
100
123
 

Sample Output
E
D
A
Score is error!

解题思路

可以用判断if-else if-结构来做;
也可以用switch:case来做

代码

#include <stdio.h>


int main()
{
    int score;
    while(scanf("%d", &score) == 1)
    {
        if(score < 0 || score > 100)    printf("Score is error!\n");
        else if(score >= 90)    printf("A\n");
        else if(score >= 80)    printf("B\n");
        else if(score >= 70)    printf("C\n");
        else if(score >= 60)    printf("D\n");
        else if(score >= 0)     printf("E\n");
    }

    return 0;
}

重点

switch case语句

switch(expression)
{
    case 1: printf();break; //expression == 1
    case 2:
    
    default: printf();
}

6. 第几天

问题描述

Problem Description
给定一个日期,输出这个日期是该年的第几天。
 

Input
输入数据有多组,每组占一行,数据格式为YYYY/MM/DD组成,具体参见sample input ,另外,可以向你确保所有的输入数据是合法的。
 

Output
对于每组输入数据,输出一行,表示该日期是该年的第几天。
 

Sample Input
1985/1/20
2006/3/12
 

Sample Output
20
71
 

解题思路

使用数组保存每个月的天数
判断闰年/平年,改变2月天数

代码

#include<stdio.h>
int main()
{
	int a,b,c;
	int d[13]={31,28,31,30,31,30,31,31,30,31,30,31};
	while(~scanf("%d/%d/%d",&a,&b,&c))
	{
		int num=0;
		for(int i=0;i<b-1;i++)
			num+=d[i];
		if(a%400==0||(a%4==0&&a%100!=0))
		{
			if(b>2)
				num+=c+1;
			else
				num+=c;
		}
		else
			num+=c;
		printf("%d\n",num);
	}
	return 0;
} 

重点

scanf取反

可以经常在ACM代码中看到 while(~scanf("%d",&n)){ } 这样的代码,意思是在读到输入结尾时循环也结束。

一般在读到输入流结尾时,scanf返回的是EOF。

EOF是在头文件stdio.h中定义的常量,一般为-1。

-1 的原码是10000001,反码是1111110,补码是11111111

~EOF则是对EOF进行按位取反操作,则为00000000。所以while条件不满足,循环结束。

7. 求n个数中奇数的乘积

问题描述

Problem Description
给你n个整数,求他们中所有奇数的乘积。
 

Input
输入数据包含多个测试实例,每个测试实例占一行,每行的第一个数为n,表示本组数据一共有n个,接着是n个整数,你可以假设每组数据必定至少存在一个奇数。
 

Output
输出每组数中的所有奇数的乘积,对于测试实例,输出一行。
 

Sample Input
3 1 2 3
4 2 3 4 5
 

Sample Output
3
15

解题思路

两个while解决输入n个数的控制问题
奇数:除以2的余数为1

代码

#include <stdio.h>
#define maxn 100000
int main()
{
    int n, x;
    int i = 0;
    int num[maxn];
    while(scanf("%d", &n) != EOF)
    {
        int ans = 1;
        while(n--){
            scanf("%d", &x);
            if(x%2 == 1)    ans *= x;
        }
        printf("%d\n", ans);
    }
    

    return 0;
}

重点

详细读题目,n个数的输入,明确了输入个数。

8. 平方和与立方和

问题描述

Problem Description
给定一段连续的整数,求出他们中所有偶数的平方和以及所有奇数的立方和。
 

Input
输入数据包含多组测试实例,每组测试实例包含一行,由两个整数m和n组成。
 

Output
对于每组输入数据,输出一行,应包括两个整数x和y,分别表示该段连续的整数中所有偶数的平方和以及所有奇数的立方和。
你可以认为32位整数足以保存结果。
 

Sample Input
1 3
2 5
 

Sample Output
4 28
20 152

解题思路

偶数 %2 == 0:pow(偶数,3)
奇数 %2 == 1:pow(奇数,3)

代码

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

int main()
{
    int x, y;
    //int even_sum = 0;
    //int odd_sum = 0;
    while(~scanf("%d %d", &x, &y)){
        int even_sum = 0;
        int odd_sum = 0;

        if(x > y){
            int temp;
            temp = x;
            x = y;
            y = temp;
        }

        for(;x <= y; x++)
        {
            if(x%2 == 0) even_sum += pow(x, 2);
            else odd_sum += floor(pow(x, 3) + 0.5);
        }

    printf("%d %d\n", even_sum, odd_sum);
    }
    
    return 0;
}

重点

考虑输入大小问题

pow(5, 3)在整型int输出使会舍入为124,不会返回125

**更安全的写法 floor(pow(x, 3) + 0.5) **

9. 数值统计

问题描述

Problem Description
统计给定的n个数中,负数、零和正数的个数。
 

Input
输入数据有多组,每组占一行,每行的第一个数是整数n(n<100),表示需要统计的数值的个数,然后是n个实数;如果n=0,则表示输入结束,该行不做处理。
 

Output
对于每组输入数据,输出一行a,b和c,分别表示给定的数据中负数、零和正数的个数。
 

Sample Input
6 0 1 2 3 -1 0
5 1 2 3 4 0.5
0 
 

Sample Output
1 2 3
0 0 5

解题思路

注意条件 n=0,break

代码

#include <stdio.h>

int main()
{
    int n;
    double x;
    while(scanf("%d", &n) != EOF){
        int num_negative = 0;
        int num_zero = 0;
        int num_positive = 0;

        if(n == 0)  break;
        while(n--)
        {
            scanf("%lf", &x);
            if(x > 0) num_positive += 1;
            else if(x < 0) num_negative += 1;
            else num_zero += 1;
        }
        printf("%d %d %d\n", num_negative, num_zero, num_positive);
    }

    return 0;   
}

重点

仔细看题

10. 求数列的和

问题描述

Problem Description
数列的定义如下:
数列的第一项为n,以后各项为前一项的平方根,求数列的前m项的和。
 

Input
输入数据有多组,每组占一行,由两个整数n(n<10000)和m(m<1000)组成,n和m的含义如前所述。
 

Output
对于每组输入数据,输出该数列的和,每个测试实例占一行,要求精度保留2位小数。
 

Sample Input
81 4
2 2
 

Sample Output
94.73
3.41

解题思路

不想写了,想什么写什么

代码

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

int main()
{
    double n;
    while(scanf("%lf", &n) != EOF)
    {
        double ans = 0.0;
        int m;
        scanf("%d", &m);
        while(m--){
            ans += n;
            n = sqrt(n);
        }
        printf("%.2f\n", ans);
    }

    return 0;
}

重点

同上

posted @ 2019-02-19 22:35  wemo  阅读(1914)  评论(0编辑  收藏  举报