• 算法竞赛入门经典第二章习题解答


    本章的题目需用文件输入输出,如果题目代号为abc,那么输入文件为abc.in,输出文件为abc.out。如果对文件操作不熟练,请尽量把fopen和freopen两种方法都尝试一下。

    注:本次解答中前4题给出两种方法,第五题采用fopen方法,其余均采用重定向方法。

    习题2-1 位数(digit)

    问题描述:输入一个不超过10^9的正整数,输出它的位数。例如12735的位数是5.请不要使用任何数学函数,只用四则运算和循环语句实现。

    重定向版:

    #define LOCAL
    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    using namespace std;
    int main()
    {
        #ifdef LOCAL
          freopen("digit.in","r",stdin);
          freopen("digit.out","w",stdout);
        #endif // LOCAL
        int n,cnt=1;
        scanf("%d",&n);
        while(n/10)
        {
            cnt++;
            n/=10;
        }
        printf("位数:%d
    ",cnt);
    }
    

    fopen版:

    #include<stdio.h>
    int main()
    {
        FILE *fin,*fout;
        fin=fopen("digit.in","rb");
        fout=fopen("digit.out","wb");
    
        int n,cnt=1;
        fscanf(fin,"%d",&n);
        while(n/10)
        {
            cnt++;
            n/=10;
        }
        fprintf(fout,"位数:%d
    ",cnt);
        fclose(fin);
        fclose(fout);
        return 0;
    }
    

    习题2-2 水仙花数(daffodil)

    问题描述:输出100~999中所有的水仙花数。若三位数ABC满足ABC=A^3+B^3+C^3;则称其为水仙花数,例如153=1^3+5^3+3^3,所以153是水仙花数。

    重定向版:

    #define LOCAL
    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    int main()
    {
        #ifdef LOCAL
            freopen("daffodil.in","r",stdin);
            freopen("daffodil.out","w",stdout);
        #endif // LOCAL
        int a=0,b=0,c=0;
        for(int i=100;i<=999;i++)
        {
            a=i%10;
            b=i/10%10;
            c=i/100;
            if(i==(pow(a,3)+pow(b,3)+pow(c,3)))
            {
                printf("%d ",i);
            }
        }
        printf("
    ");
    }
    

    fopen版:
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<iostream>
    #include<fstream>
    using namespace std;
    int main()
    {
        FILE *fout;
        fout=fopen("daffodil.out","wb");
    
        int a=0,b=0,c=0;
        for(int i=100;i<=999;i++)
        {
            a=i%10;
            b=i/10%10;
            c=i/100;
            if(i==(pow(a,3)+pow(b,3)+pow(c,3)))
            {
                fprintf(fout,"%d ",i);
            }
        }
        fprintf(fout,"
    ");
        fclose(fout);
    }


    习题2-3 韩信点兵(hanxin)

    问题描述:相传韩信才智过人,从不直接清点自己军队的人数,只要让士兵先后以三人一排、五人一排、七人一排德变换队形,而他每次只掠一眼队伍的排尾就知道总人数了。输入三个非负整数a,b,c,表示每种队形排尾的人数(a<3,b<5,c<7),输出总人数的最小值(或报告无解)。已知总人数不小于10,不超过100。

    重定向版:

    #define LOCAL
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    using namespace std;
    int a,b,c;
    int main()
    {
        #ifdef LOCAL
          freopen("hanxin.in","r",stdin);
          freopen("hanxin.out","w",stdout);
        #endif // LOCAL
        while(scanf("%d%d%d",&a,&b,&c)==3)
        {
            bool flag=false;
            int num;
            for(int i=10;i<=100;i++)
            {
                if(i%3==a&&i%5==b&&i%7==c)
                {
                    flag=true;
                    num=i;
                    break;
                }
            }
            if(flag==true)
            {
                printf("%d
    ",num);
            }
            else
            {
                printf("No answer
    ");
            }
        }
    }
    

    fopen版:

    #include<iostream>
    #include<fstream>
    #include<stdio.h>
    using namespace std;
    int main()
    {
        FILE *fin,*fout;
        fin=fopen("hanxin.in","rb");
        fout=fopen("hanxin.out","wb");
        int a,b,c;
        while(fscanf(fin,"%d%d%d",&a,&b,&c)==3)
        {
            bool flag=false;
            int num;
            for(int i=10;i<=100;i++)
            {
                if(i%3==a&&i%5==b&&i%7==c)
                {
                    flag=true;
                    num=i;
                    break;
                }
            }
            if(flag==true)
            {
                fprintf(fout,"%d
    ",num);
            }
            else
            {
                fprintf(fout,"No answer
    ");
            }
        }
        fclose(fin);
        fclose(fout);
        return 0;
    }

    习题2-4 倒三角形(triangle)

    问题描述:输入正整数n<=20,输出一个n层的倒三角形。例如n=5时输出如下:

    #########

      #######

        #####

         ###

           #

    重定向版:

    #define LOCAL
    #include<iostream>
    #include<stdlib.h>
    #include<stdio.h>
    using namespace std;
    int main()
    {
        #ifdef LOCAL
           freopen("triangle.in","r",stdin);
           freopen("triangle.out","w",stdout);
        #endif // LOCAL
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<i;j++)
            {
                printf(" ");
            }
            for(int j=1;j<=(n-i+1)*2-1;j++)
            {
                printf("#");
            }
            printf("
    ");
        }
    }

    fopen版:

    #include<iostream>
    #include<stdlib.h>
    #include<fstream>
    #include<stdio.h>
    using namespace std;
    int main()
    {
        FILE *fin,*fout;
        fin=fopen("triangle.in","rb");
        fout=fopen("triangle.out","wb");
        int n;
        fscanf(fin,"%d",&n);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<i;j++)
            {
                fprintf(fout," ");
            }
            for(int j=1;j<=(n-i+1)*2-1;j++)
            {
                fprintf(fout,"#");
            }
            fprintf(fout,"
    ");
        }
    }
    


    习题2-5 统计(stat)

    问题描述:输入一个正整数n,然后读取n个正整数a1,a2,a3.......an,最后再读取一个正整数m。统计a1,a2,a3........an中有多少个整数的值小于m。

    提示:如果重定向和fopen都可以使用,那个比较方便。

    选择fopen,因为fopen可以反复打开并读写文件。

    fopen版:

    #include<stdio.h>
    #include<stdlib.h>
    #include<fstream>
    int main()
    {
        FILE *fin,*fout;
        fin=fopen("stat.in","rb");
        fout=fopen("stat.out","wb");
    
        int n,a[10000];
        fscanf(fin,"%d",&n);
        for(int i=0;i<n;i++)
        {
            fscanf(fin,"%d",&a[i]);
        }
        int m;
        fscanf(fin,"%d",&m);
        int cnt=0;
        for(int i=0;i<n;i++)
        {
            if(a[i]<m)
            {
                cnt++;
            }
        }
        fprintf(fout,"%d
    ",cnt);
        fclose(fin);
        fclose(fout);
    }

    习题2-6 调和级数(harmony)

    问题描述:输入正整数n,输出H(n)=1+1/2+1/3+......+1/n的值,保留三位小数。例如n=3时,答案为1.7=833。

    重定向方法:

    #define LOCAL
    #include<stdio.h>
    #include<stdlib.h>
    #include<iostream>
    using namespace std;
    int main()
    {
        #ifdef LOCAL
           freopen("harmony.in","r",stdin);
           freopen("harmony.out","w",stdout);
        #endif // LOCAL
        int n;
        scanf("%d",&n);
        double res=0;
        for(int i=1;i<=n;i++)
        {
            res+=1.0/i;
        }
        printf("%.3lf
    ",res);
        return 0;
    
    }
    

    习题2-7 近似计算(approximation)

    问题描述:计算PI/4=1-1/3+1/5-1/7+......,直到最后一项小于10^(-6)。

    重定向方法:

    #define LOCAL
    #include<stdio.h>
    #include<stdlib.h>
    #include<iostream>
    #include<cmath>
    using namespace std;
    int main()
    {
        #ifdef LOCAL
           freopen("approximation.in","r",stdin);
           freopen("aproximation.out","w",stdout);
        #endif // LOCAL
        int i=1,sign=-1;
        double res=1;
        do
        {
            res+=1.0/(2*i+1)*sign;
            i++;
            sign=-sign;
        }while(fabs(1.0/(2*i+1))>=10e-6);
        printf("%lf
    ",4*res);
        return 0;
    
    }
    

    习题2-8 子序列的和(subsequence)

    问题描述:输入两个整数n<m<10^6,输出1/(n^2)+1/((n+1)^2)+.....+1/(m^2),保留5位小数。例如n=2,m=4时答案是0.42362;n=65536,m=655360时答案是0.00001。

    注意:本题有陷阱。

    重定向方法:

    #define LOCAL
    #include<stdio.h>
    #include<stdlib.h>
    #include<iostream>
    #include<cmath>
    using namespace std;
    int main()
    {
        #ifdef LOCAL
           freopen("subsequence.in","r",stdin);
           freopen("subsequence.out","w",stdout);
        #endif // LOCAL
        int n,m,i;
        double res=0;
        scanf("%d%d",&n,&m);
        for(int i=n;i<=m;i++)
            res+=1.0/((long long)i*i;
        printf("%.5lf
    ",res);
        return 0;
    }


    习题2-9 分数化小数(decimal)

    问题描述:输入整数a,b,c,输出a/b的小数形式,精确到小数点后c位。a,b<=10^6,c<=100。例如:a=1,b=6,c=4时应输出0.1667。

    重定向方法:

    #define LOCAL
    #include<stdio.h>
    #include<stdlib.h>
    #include<iostream>
    #include<cmath>
    using namespace std;
    int main()
    {
        #ifdef LOCAL
           freopen("decimal.in","r",stdin);
           freopen("decimal.out","w",stdout);
        #endif // LOCAL
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        cout.setf(ios::fixed);
        cout.setf(ios::showpoint);
        cout.precision(c);
        cout<<(double)a/(double)b;
        return 0;
    }
    

    习题2-10 排列(permutation)

    问题描述:用1,2,3...,9组成3个三位数abc,def和ghi,每个数字恰好使用一次,要求abc:def:ghi=1:2:3,输出所有解。提示:不必太动脑筋。

    重定向方法:

    #define LOCAL
    #include<stdio.h>
    #include<stdlib.h>
    #include<iostream>
    #include<cmath>
    using namespace std;
    //用1,2,3……,9组成3个三位数abc,def和ghi,每个数字恰好使用一次,要求abc:def:ghi=1:2:3.输出所有解。
    
    #include <stdio.h>
    
    void result(int num, int &result_add, int &result_mul)
    {
        int i, j, k;
    
        i = num / 100;        //百位
        j = num / 10 % 10;    //十位
        k = num % 10;         //个位
    
        result_add += i + j + k;    //分解出来的位数相加
        result_mul *= i * j * k;    //相乘
    }
    
    int main()
    {
        #ifdef LOCAL
        // freopen("permutation.in","r",stdin);
           freopen("permutation.out","w",stdout);
        #endif // LOCAL
        int i, j, k;
        int result_add, result_mul;
        for(i = 123; i <=329; i++)
        {
            j = i * 2;
            k = i * 3;
            result_add = 0;
            result_mul = 1;
            result(i, result_add, result_mul);
            result(j, result_add, result_mul);
            result(k, result_add, result_mul);
    
            if(result_add == 45 && result_mul == 362880)
                printf("%d %d %d
    ", i, j, k);
        }
        return 0;
    }
    


    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    java中map接口hashMap以及Enty之间的用法和关系
    Collection集合总结,List和set集合的用法,HashSet和LinkedHashSetde用法
    微信小程序开发攻略
    Java闰年的计算,Calendar的用法
    Java计算计算活了多少天
    Java用代码演示String类中的以下方法的用法
    Java判断一个字符串中有多少大写字母、小写字母和数字
    Java将一个字符串的首位改为大写后边改为小写的实现,String
    Java 获取一个字符串中,另一个字符串出现的次数
    linux下重命名文件或文件夹(linux)
  • 原文地址:https://www.cnblogs.com/Tobyuyu/p/4965617.html
Copyright © 2020-2023  润新知