zoukankan      html  css  js  c++  java
  • 算法竞赛入门经典第二章习题解答

    本章的题目需用文件输入输出,如果题目代号为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;
    }
    


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

  • 相关阅读:
    状态压缩 + 暴力 HDOJ 4770 Lights Against Dudely
    简单几何(推公式) UVA 11646 Athletics Track
    简单几何(四边形形状) UVA 11800 Determine the Shape
    简单几何(求交点) UVA 11437 Triangle Fun
    计算几何模板
    简单几何(相对运动距离最值) UVA 11796 Dog Distance
    简单几何(求划分区域) LA 3263 That Nice Euler Circuit
    覆盖的面积 HDU
    Desert King 最小比率生成树 (好题)
    约会安排 (区间合并)毒瘤题
  • 原文地址:https://www.cnblogs.com/Tobyuyu/p/4965618.html
Copyright © 2011-2022 走看看