算法競賽入門經典第二章習題解答與分析

習題

水仙花數

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

int main()
{
    int hunderds=0,tens=0,ones=0;
    int i;
    for(i=100;i<1000;i++)
    {
        hunderds=i/100;
        tens=(i%100)/10;
        ones=i%10;
    if(i == (int)(pow(hunderds,3)+pow(tens,3)+pow(ones,3)))
        printf("%d ",i);
    }
    return 0;
}
/*掌握POW函數的用法,不加(int)與有(int)答案存在區別*/

韓信點兵

#include<stdio.h>

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

    int a=0,b=0,c=0;
    int count=0,n=0,i=0,kase=0; /*count:計數標誌位。判斷輸入a, b, c*/
    int  flag=1,flag2=1;/*flag:遍歷完成後判斷是否無答案,flag2判斷是否已接收到三位數字*/
    while(scanf("%d",&n) == 1)
    {
        count++;
        switch (count)
        {
        case 1:
            a=n;
            break;
        case 2:
            b=n;
            break;
        case 3:
            c=n;
            count=0;
            flag2=0;
            break;
        default:
            printf("worry");
            break;
        }
    if(flag2==0)
        {
            flag=1;
            flag2=1;
            for(i=10; i<=100; i++)
            {
                if(i%3==a && i%5==b && i%7==c)
                    {
                        printf("Case %d: %d\n", ++kase, i); //怎樣輸出NO answer,用flag試試
                        flag =0;
                    }
            }
            if(flag)
            {
                printf("Case %d: No answer\n", ++kase);
            }
        }
    }
    return 0;
}
/*練習使用重定向方式
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
*/

仍然存在的問題:
while(scanf("%d",&n) == 1),按照書中所講,輸入Enter後並不會顯示結果,因爲在scanf的輸入格式中,空格,tab和回車符都是無關緊要的。而在我的代碼中,輸入三個數字後按Enter會直接輸出結果。按照書中提示2-9:在Window下,輸入完畢後先按Enter鍵,再按Ctrl+Z鍵,最後再按Enter鍵,即可結束輸入。實驗下程序2-9看看,實現結果與書中相同,問題來了。測試發現,printf()函數不能放在這個while循環的裏面,如果放在裏面的話就會出現上述的問題。去找找標準答案看看是怎麼寫的吧。

倒三角形

#include<stdio.h>

int main()
{
    int i, j, n, p;
    scanf("%d", &n);
    for(i=n; i>0; i--)
    {
        for(p=0;p<(n-i);p++)
            printf("  "); //兩個空格
        for(j=0; j<1+2*(i-1); j++) //理清每行的表達式
        {
            printf("# ");
        }
        printf("\n"); //換行符不要忘記
    }
    return 0;
}

子序列的和

#include<stdio.h>
#include<math.h>
/* 本題有陷阱*/

int main()
{
    int x, m, n, count=0, i, kase=0;
    double sum=0;
    while(scanf("%d", &x) == 1)
    {
        count++;
        if(count == 1)
            n=x;
        else
        {
            m=x;
            count=0;
        }
        if(n == 0 && m == 0)
            break;
        if(count == 0)
        {
            for(i=n; i<=m; i++)
                sum += (double)(1.0/pow(i,2));
            printf("Case %d: %.5f\n", ++kase, sum);
        }
    }
    return 0;
}
/*成功掉入陷阱,第二個樣例輸出不對*/

分數化小數

這個題目不會,關鍵是得精確到小數點後100位,比較爲難。

排列

不知道怎麼判斷沒一位都不同。如果全部遍歷判斷的話邏輯會混亂

答案

參考答案鏈接

習題2-1:結果與答案一致
習題2-2:答案如下

#include<stdio.h>
int main()
{
    int i, a, b, c;
    scanf("%d%d%d", &a, &b, &c);
    for(i=10; i<100; i++)
    {
        if(i%3==a && i%5==b && i%7==c)
        {
            printf("%d", i);
        }
        if(i == 101)
            printf("No answer");
    }
    return 0;
}

int main()
{
    int i, j, n, p;
    scanf("%d", &n);
    for(i=n; i>0; i--)
    {
        for(p=0;p<(n-i);p++)
            printf("  "); //兩個空格
        for(j=0; j<1+2*(i-1); j++) //理清每行的表達式
        {
            printf("# ");
        }
        printf("\n"); //換行符不要忘記
    }
    return 0;
}



也是無法做到一直輸入,直到按Enter+(Ctrl+Z)+Enter才停止,所以我可能理解錯了題目的意思,第二個答案鏈接還是無法做到一直輸入,但是它這樣寫可以去掉count與flag。
反正如果使用重定向,這兩個答案結果是相符的。
習題2-3:與答案基本一致,只不過空格數目有區別,沒空格還沒我的好看
習題2-4

#include<stdio.h>

int main()
{
    long  n, m;
    double sum = 0.0;
    while(scanf("%d%d"), &n, &m)
    {
        if(n == 0 && m == 0)
            break;
        for(int i=n; i<=m; i++)
        {
            sum += (double)((1.0/(double)i)*(1.0/(double)i));//直接1.0/(i*i)就炸
//sum += 1 / (((double)n + i) * ((double)n + i));
//在n較大時,((double)n + i) * ((double)n + i)會溢出,
//所以應該改成 1 / ((double)n + i) / ((double)n + i)
        }
         printf("%.5f\n", sum);
    }
    return 0;
}

還是有錯誤,0.00001顯示不出來

習題2-5:參考代碼 參考代碼1鏈接
參考代碼2鏈接


#include <iostream>
#include  <cstring>
#include   <cstdio>
#include    <cmath>

int main()
{
    int a,b,c;//2-5分數化小數 decimal
    while(scanf("%d%d%d",&a,&b,&c)==3 )
    {
        if( a== b && b==c && a==0)break;
        int aa[505],bb[505];
        aa[0] = a/b;
        aa[1] = a*10/b;

        for(int i=2; i <= c+1;i++)
        {
            bb[i] = a*10%b;
            aa[i] = bb[i]*10/b;
        }//printf("%d.",aa[0]);
        if(aa[c+1] >= 5 )aa[c] += 1;
        for(int i=c; i >= 1 ;i--)
            if(aa[i] == 10)
                aa[i]-=10,aa[i-1]+1;
        printf("%d.",aa[0] );
        for(int i=1; i < c; i++)
            printf("%d",aa[i] );
        printf("%d\n",aa[c]);
    }
    while(scanf("%d%d%d",&a,&b,&c) == 3 && a)
    {
            //if(a <= 1e+6 && b <= 1e+6 && c <= 200 && a != 0 && b != 0 && c != 0){
        printf("%.*lf\n",c,(double)a / (double)b);
        //}

    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章