学习ACM之旅(一)——菜鸟入门

ACM系列:入门

——————————————————————————

    每次开始新的博客系列之前,都会来一堆废话。作为一个计算机专业的人来说,不会算法总是感觉自己是真的垃圾。也有学长的衷心劝告,作为一名程序猿,在本科阶段还是要抽出至少一年的时间去搞搞ACM,还有我舍友的意见,计算机专业的人不会算法在研究生或者找工作都会被虐的很惨,细思恐惧,可惜我已经浪费了太多的时间,已是大三的老人,也许现在开始还不晚。。。

    大概是分为三个部分去整理自己的学习笔记,第一个是C语言的东西,第二个是基础操作,偏向数据结构,第三个就是竞赛题目的操作了。第一步C语言可能就是要去掉脑子里所装的C语言中最没用的那些部分,去掉考试最爱考的那些,emmmm,剩下那些在实际开发中还能有所作用的东西,此中有真意~。嗯,开始吧。

1. 程序设计初始

    1.1 基础操作
    虽然已经学过了C语言,还用C语言写过点东西,但还是从头开始吧,从最基础的int a开始。

#include <stdio.h>

int main()
{
    printf("%d\n", 1 + 2);
    printf("%d\n", 8 / 5);  //整数与整数的运算的结果是整数
    printf("%.1f\n", 8.0 / 5);  //浮点数与浮点数运算的结果是浮点数
    return 0;
}

    输出的结果如下:

3
1
1.6

    1.2 变量及其输入
    以计算一个圆柱的面积为例,输入底面半径 r ,高 h ,计算表面积 A r e a

    样例输入:3.5 9

    样例输出:Area = 274.889

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

int main()
{
    float a, b;
    float s1, s2;
    const float PI = acos(-1.0);
    scanf("%f%f", &a, &b);
    s1 = PI * a * a * 2;
    s2 = 2 * PI * a * b;
    printf("Area = %.3f", s1 + s2);
    return 0;
}

    程序的运行结果:

3.5 9
Area = 274.889

   注意事项:不要在用户输入之间加入乱七八糟的东西,比如”Please input radius and height”,这样不会赢得界面友好分,还比标准答案多了一行,多此一举还不讨好。还有多余的getchar()也不要加,每行以回车作为结束符,每行的开始不能有空格,每行的结尾可以有任意的空格,输出的两个数字或者字符数组以单个空格隔开。读入数据,打印结果,程序退出即可,没必要用getchar去暂停程序观看结果。

    1.3 做几个例子熟悉这种风格。

    样例输入:250。样例输出:052。

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

int main()
{
    int n, m;
    scanf("%d", &n);
    m = (n % 10) * 100 + (n /10 % 10) * 10 + n / 100;
    printf("%03d\n", m);   //输出三位,高位补0
    return 0;
}

    样例输入:14,15。样例输出:15,14。

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

int main()
{
    int n, m;
    scanf("%d,%d", &n, &m);
    printf("%d,%d\n", m, n);  //没说要交换变量,意不意外
    return 0;
}

                                                             本小节结束
—————————————————————————————————————————————————————–

2. 循环程序设计

    以下的复习内容会以实例为主,穿插着一些细微的知识点,毕竟纸上得来终觉浅。

    2.1 for 循环
    搜寻10000以内形如aabb式的完全平方数。

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

int main()
{
    int n;
    float m;
    for (int i = 1; i < 10; i++)        //先执行i++,在判断i<10是否成立
        for (int j = 1; j < 10; j++)
        {
            n = i * 1100 + j + j * 10;
            m = sqrt(n) + 0.5;
            m = floor(m);
            if (m * m == n)
            {
                printf("%d\n", n);
            }
        }

    return 0;
}

    然而,众所周知,涉及到开平方终究会涉及到浮点的精度问题,判断两个浮点数是否相等,一般会采取(a-b<1e-7)这样的形式,因此采取了floor(向下取整,1.5=1,1.9=1)。但是感觉精度不容易控制呢?那就不如用枚举的暴力形式去求解。

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

int main()
{
    int n, x, a, b, c, d;
    for (n = 1; ; n++)
    {
        x = n * n;
        if (x < 1000)
            continue;      //continue 跳过下面的语句,重新开始循环
        if(x > 9999)
            break;         //break 跳出循环
        a = x / 1000;
        d = x % 1000 % 100 % 10;
        b = (x / 100) % 10 ;
        c = (x /10) % 100 % 10;
        if (a == b && c == d)
            printf("%d\n", x);

    }
    return 0;
}

    2.2 while与do-while。
    对于大于1的自然数 n ,若其为奇数, n = 3 n + 1 ,若其为偶数, n = n / 2 ,最终 n 一定会变为 1 ,输出其变换次数。

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

int main()
{
    int n, count = 0;  //初始化变量
    scanf("%d", &n);
    while (n > 1)    // n>1时执行此循环
    {
        if (n % 2 == 1)
        {
            n = 3 * n + 1;
            count++;
        }

        else 
        {
            n = n / 2;
            count++;
        }

    }
    printf("%d\n", count);

    return 0;
}

    然而上面的程序有问题,why?因为当你输出的数太大时,会导致精度溢出,两种方案,一种是换成unsigned int类型,另一种是long long类型,但是long long 类型在linux下的输入输出格式为%lld,Windows平台下有时为%I64d,为了保险起见,可以用C++流,这里不做介绍。

    2.3 循环的代价
    写个循环,看看你的程序执行的多长的时间。计算 S = 1 ! + 2 ! + 3 ! + . . . + n ! 共计花费多长时间。

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

int main()
{
    int n, sum = 0;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
    {
        int temp = 1;
        for (int j = 1; j <= i; j++)
        {
            temp = temp * j;
        }
        sum = sum + temp;
    }
    printf("%06d\n", sum % 1000000);
    printf("time used :%.2fs", (double)clock() / CLOCKS_PER_SEC);

    return 0;
}

    遗憾的是,输入数据的时间也被记在算法的执行时间内,我们想要核心算法的执行时间,How to deal it?方法总比问题多,在命令行输入:

echo 20|test.c  //20作为输入,test.c是程序的文件名

//以下是执行部分
C:\Users\暮\Desktop\ACM\second\second\Debug>echo 20 | second.exe
040729
time used :0.00s

    2.3 算法竞赛的输入输出框架(待续)
    * *

猜你喜欢

转载自blog.csdn.net/asd20172016/article/details/81077888