算法竞赛入门经典第二版:循环结构程序设计实例与习题

实例:
1.阶乘之和
输入n,计算S= 1!+2!+3!+…+n!的末六位。
分析:两个循环,里面循环用于计算不同数的阶乘,外面一个循环用于将所有阶乘相加,核心算法

"for(int i=1; i<=n ;i++) S+=i!" //伪代码	

可以同时加一个计时器测试程序的运行速度

#include 
#include 
#include 

int main()
{
    const int MOD = 1000000;
    int n, S = 0;
    scanf("%d", &n);

    for(int i = 1; i <= n; i++)
    {
        int factorial = 1;
        for(int j = 1; j <= i; j++)
            factorial = (factorial * j % MOD);
        S = (S + factorial) % MOD;
    }
    printf("%d\n",S);
    printf("Time used = %.2f\n", (double)clock()/ CLOCKS_PER_SEC); //clock()返回的是程序开始后所用的系统时间,但是单位不是秒,而CLOCK_PER_SEC是每秒的系统时间单位常量,所以除以它就是经过了多少秒
    return 0;
}

还有很多问题不明白
25!末尾6个0所以就之后的所有项都是940313,这是什么意思,没太明白
明白了,可以吧这六个0象作10的6次方,所以25!之后的所有项与25!相乘都会有10的六次方与他们相乘,所以就是所有的项都将起码6个0.所以后六位的数据就不会再变了

2.4 算法竞赛中的输入输出框架
实例1:

连续输入1000以内的整数,求出最小最大与平均值

#include 
#define INF 100000

int main()
{
    int x, n = 0, min = INF, max = -INF, s = 0;
    while(scanf("%d", &x) == 1)  //scanf的返回值是输入的变量数
    {
        s += x;
        if(x < min) min = x;     //如果不对min和max进行初始化,则会出现一个随机的初值
        if(x > max) max = x;   //有可能这个初值大于所有输入的值,所以不能让min或max更新,所以需要设定一个初值
        n++;
    }
    printf("%d %d %.3f\n", min, max, (double)s/n);
    return 0;
}

使用文件最简单的方法是使用输入输出重定向,只需在main函数的入口处加入下两条语句

freopen("input.txt","r",stdin);
freopen("output.txt", "w", stdout);

这两条语句将程序所有的输入和输出都改为文件。

可以利用

#define LOCAL
#ifdef LOCAL
...
#endif

用这种来选择性编译中间的语句
实例2
输入包含多组数据,每组数据第一行是整数个数n,第二行是n个整数,n=0是输入结束的标记,相邻两组数据间输出空行

#include 
#define INF 100000

int main()
{
    int x, n = 0,  kase = 0;
    while(scanf("%d", &n) == 1 && n)
    {
        int s = 0;
        int max = -INF;
        int min = INF;
        for(int i = 0; i < n; i++)
        {
            scanf("%d", &x);
            s += x;
            if(x < min) min = x;
            if(x > max) max = x;
        }
        if(kase)    printf("\n");
        printf("case %d:%d %d %.3f\n", ++kase, min, max, (double)s/n);
    }
    return 0;
}

当有循环的时候,就要考虑这个循环有没有跳出循环的能力,如果在while的判断条件里,没有与上n = 0;那就需要在控制台程序中ctrl+z才能手动跳出循环,因为scanf函数是对回车空格等免疫的,不能达到结束输入的效果

习题:

  1. 水仙花数
    输出100~999中的水仙花数,三位数ABC = A3+ B3 + C3;则该数为水仙花数。

知识点

  • 想用pow()函数算立方来着,但是取余的操作不能对double使用
#include 
#include 

int main()
{

    for (int n = 100; n < 1000; n++)
    {
        if((n / 100)*(n / 100)*(n / 100) + (n / 10 % 10)*(n / 10 % 10)*(n / 10 % 10) + (n % 10)*(n % 10)*(n % 10) == n)
            printf("%03d\n", n);
    }
    return 0;
}

题目2:让士兵先后一三人一排,五人一排,七人一排的变换阵型,掠翼岩队伍的排尾就知道总人数。输入韩多组数据,魅族数据包含三个非负整数a,b,c,表示每种队形排尾的人数(a<3, b<5, c<7), 输出总人数的最小值(或报告无解)。一直总人数不小于10,不大于100,输入到文件结束为止

知识点

  • 除以三余数,除以五余数,除以七余数
  • 稍微要注意的是对case的计数君的定义要放在循环外
  • 对用eof来判断文件输出结尾的应用,用户自己输入的时候是用CTRL+Z来触发
#include 

int main()
{
    int a,b,c;
    int ca = 1;
    while(scanf("%d %d %d", &a, &b, &c) != EOF)
    {

        for(int amount = 10; amount < 101; amount++)
        {
            if(amount % 3 == a && amount % 5 == b && amount % 7 == c)
               {
                   printf("case %d :%d\n", ca , amount);
                   ca++;
                   break;
               }
            else if(amount == 100)
                {printf("case %d :no answer\n",ca);
                 ca++;}
        }

    }

}


题目三:输入两个正整数n6,输出1/n2到1/m2的和,结束标记为m = n = 0.
知识点:

  • 直接在while里面设置循环条件的话不好设置,我没想出来。
  • 临时变量每次循环得重置
#include 
#include 
int main()
{
    int m, n;
    int count = 0;

    while(scanf("%d %d", &n, &m))
    {
        double temp = 0;
        count++;
        if(m == n && m == 0 && n == 0)
        {
            break;
        }
        else
        {
            for(int i = n; i <= m; i++)
            {
                temp += 1/pow((double)i ,2);
            }
            printf("case %d: %.5f\n", count, temp);

        }

    }
}

题目四:分数化小数
知识点:

  • 我不知道怎么才能做到手动用c语言设定精度,最终做到的结果就是不能四舍五入的方法来保留小数,可以说还是错的,但是不知道怎么做
#include 
#include 
int main()
{
    int n, m, j;
    int count = 0;

    while(scanf("%d %d %d", &n, &m, &j))
    {
        double temp = 0;
        count++;
        if(m == n && m == 0 && n == 0 && n == j && j == 0)
        {
            break;
        }
        else
        {
            temp = ((double)n) / ((double)m);				
            temp = floor(pow(10, j)*temp)/ pow(10, j); 	//将小数点后j位以后置零
            printf("case %d: %g\n", count, temp); 		//%g忽略末尾的零输出
        }

    }
}

你可能感兴趣的:(编程练习,算法)