zoukankan      html  css  js  c++  java
  • 第5章 基础题目选解

    学习目标:

         学会用常量表简化代码

         学会用状态变量辅助字符串读入

         学会用结构体定义高精度证书,并设计构造函数、复制构造函数和输入输出方法

         学会为结构体定义“小于”运算符,并用它定义其他比较运算符

         熟悉掌握冒泡排序和排序检索

         熟练掌握用qsort库函数给整数和字符串排序的方法

         熟练掌握小规模素数表的构造方法

         熟练掌握素因子分解的方法

         熟练掌握三角形有向面积的意义和计算方法

         完成一定数量的编程练习

    5.1.1  WERTYU

         把手放在键盘上时,稍不注意就会往右错一位。这样的话,Q会变成W,J会变成K等。输入一个错位后敲出的字符串,输出打字员本来想打出的句子。

         样例输入:Q S, GOMR YPFSU/

         样例输出: I AM FINE TODAY.

    代码:

    #include<stdio.h>
    #include<string.h>
    char *s="`1234567890-=QWERTYUIOP[]\ASDFGHJKL;'ZXCVBNM,./";//定义一个常数数组 
    int main()
    {
        int i;
        char c;
        while((c=getchar())!=EOF)
        {
            for(i=1;s[i]&&s[i]!=c;i++);//此处的;千万不可以省去 
               if(s[i])
                  putchar(s[i-1]);
                else putchar(c); 
        }
        return 0; 
    } 

    5.1.2  TeX 括号
        在TeX中,左双引号是"。输入一篇包含双引号的文章,你的任务是把它转换成TeX的格式。

        样例输入:

        "To be or not to be,"quoth the Bard,"that is the question".

        样例输出:

        “To be or not to be,"quoth the Bard,“that is the question".

    代码:

    #include<stdio.h>
    int main()
    {
        int c,q=1;
        while((c=getchar())!=EOF)
        {
            if(c=='"')
            {
                printf("%s",q?"":"''" );
                q=!q;
            }
            else printf("%c",c);
        }
        return 0;
    } 

    5.1.3 周期串

    如果一个字符串可以有某个长度为k的字符串重复多次得到,我们说该串以k为周期。例如,abcabcabcabc以3为周期(注意,它也以6和12为周期)。输入一个长度不超过80的串,输出它的最小周期。

         样例输入:HoHoHo

         样例输出:2

    代码:

    #include<stdio.h>
    #include<string.h>
    int main()
    {
        int i,k,j;
        char word[100];
        scanf("%s",word);
        int len=strlen(word);
        for(i=1;i<=len;i++)
            if(len%i==0)
            {
                k=1;
                for(j=i;j<len;j++)
                    if(word[j]!=word[j%i])
                    {
                        k=0;
                        break;
                    }
                 if(k!=0)
                 {
                     printf("%d
    ",i);
                     break;
                 }
            }
        return 0;
    }

    5.2.1 小学生算术

        很多学生在学习加法时,发现“进位”特别容易出错,你的任务是计算两个整数在相加时需要多少次进位。你编制的程序应当可以连续处理多组数据,知道读到两个0(这是输入结束标记)。假设输入的整数都不超过9个数字。

       样例输入:

       123 456
       555 555
       123 594

       0     0

       样例输出:

       0
       3

       1

    代码:

    #include<stdio.h>
    int main()
    {
        int a,b;
        while(~scanf("%d %d",&a,&b))
        {
            if(a==0&&b==0)
               break;
            int c=0,ans=0;
            for(int i=9;i>=0;i--)
            {
                c=(a%10+b%10+c)>9?1:0;
                ans+=c;
                a/=10;
                b/=10;
            }
            printf("%d
    ",ans);
        }
        return 0;
    }

    5.2.2 阶乘的精确值

         输入不超过1000的正整数n,输出n!=1×2×3×……×n的精确结果。

         样例输入: 30

         样例输出: 265252859812191058636308480000000

    代码:

    #include<stdio.h>
    #include<string.h>
    const int maxn=3000;//const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是像#define一样给出的是立即数,
    //所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干份拷贝。 
    int f[maxn];
    int main()
    {
        int i,j,n;
        scanf("%d",&n);
        memset(f,0,sizeof(f));
        f[0]=1;
        for(int i=2;i<=n;i++)
        {
            int c=0;
            for(j=0;j<maxn;j++)
            {
                int s=f[j]*i+c;
                f[j]=s%10;
                c=s/10;
            }
        }
        for(j=maxn-1;j>=0;j--)
            if(f[j])  break;
        for(i=j;i>=0;i--)
            printf("%d",f[i]);
        printf("
    "); 
        return 0;
    }

    !!!!高精度运算类bign

    代码:

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <math.h>
    #include <algorithm>
    #include <string>
    #include <vector>
    #include <list>
    
    using namespace std;
    
    const int maxn = 1000;
    
    struct bign
    {
           int len, s[maxn];  //s是逆序存储
           
           bign(){ memset(s, 0 , sizeof(s)); len = 1 ; } //构造函数
           
           bign(int num) { *this  = num ; } //初始化
           
           bign(const char* num) { *this = num ; }
            
           string str() const//转换为字符串 
           {
               int i;
               string res = "";
               for( i = 0 ; i < len ; i++ ) 
                   res = (char)( s[i] + '0' ) + res ;
               if (res == "") res = "0";
               return res;
           } 
            
           bign operator = (const char* num)//赋值运算1 
           {
                int i;
                len = strlen(num);
                for( i = 0 ; i < len ; i++ )
                    s[i] = num[len-i-1] - '0' ;
                return *this; 
           } 
           
           bign operator = (int num)//赋值运算2 
           {
                char s[maxn];
                sprintf(s , "%d" , num);
                *this = s;
                return *this;
           } 
           
           bign operator + (const bign& b) const//加法 
           {
                bign c;
                c.len = 0;
                int i, g;
                for( i = 0 , g = 0 ; g || i < ( len > b.len ? len : b.len ) ; i++ )
                {
                     int x = g ;
                     if( i < len ) x += s[i] ;
                     if( i < b.len ) x += b.s[i] ;
                     c.s[c.len++] = x % 10 ;
                     g = x / 10 ;
                }
                return c;
           }
           
           //比较的前提是两个数都没有前导零 
           bool operator < (const bign& b) const
           {
                if( len != b.len ) return len < b.len ;
                int i;
                for( i = len-1 ; i >= 0 ; i-- )
                    if( s[i] != b.s[i] ) return s[i] < b.s[i];
                return false;
           }
           bool operator > (const bign& b) const { return b < *this; }
           bool operator <= (const bign& b) const { return !(b < *this); } 
           bool operator >= (const bign& b) const { return !(*this < b); } 
           bool operator != (const bign& b) const { return b < *this || *this < b; } 
           bool operator == (const bign& b) const { return !(b < *this) || !(*this < b); }  
    };
    
    istream& operator >> (istream &in , bign& x)//定义<<运算符 
    {
             string s;
             in >> s;
             x = s.c_str();
             return in;
    }
    ostream& operator << (ostream &out , const bign& x)//定义>>运算符 
    {
             out << x.str();
             return out;
    }


     5.3.1 6174问题

        假设你有一个各种数字互不相同的四位数,把所有数字从大到小排序后得到a,从小到大排序得到b,然后用a-b替换原来这个数,并且继续操作。例如,从1234出发,依次可以得到4321-1234=3087、8730-378=8352、8532-2358=6174、7641-1467=6174,回到了它自己。

        输入一个n位数,输出操作序列,直到出现循环(即新得到的数曾经得到过)。输入保证在循环之前最多只会产生1000个整数。

        样例输入:1234

        样例输出:1234->3087->8352->6174->6174

    代码:

    #include<stdio.h>
    #include<string.h>
    
    int get_next(int x)
    {
        int a,b,n;
        char s[10];
        sprintf(s,"%d",x);//字符串格式化命令,主要功能是把格式化的数据写入某个字符串中。sprintf 是个变参函数。
        n=strlen(s);
        for(int i=0;i<n;i++)
            for(int j=i+1;j<n;j++)
                if(s[i]>s[j])
                {
                    char t=s[i];
                    s[i]=s[j];
                    s[j]=t;
                }
        sscanf(s,"%d",&b);//sscanf() - 从一个字符串中读进与指定格式相符的数据. 
        for(int i=0;i<n/2;i++)
        {
            char t=s[i];
            s[i]=s[n-1-i];
            s[n-1-i]=t;
        }
        sscanf(s,"%d",&a);
        return a-b;
    }
    
    int num[2000],count;
    int main()
    {
        scanf("%d",&num[0]);
        printf("%d",num[0]);
        count=1;
        for(;;)
        {
            num[count]=get_next(num[count-1]);
            printf("->%d",num[count]);
            int found=0;
            for(int i=0;i<count;i++)
                if(num[i]==num[count])
                {
                    found=1;
                    break;
                }
            if(found)
                break;
            count++;
        }
        printf("
    ");
        return 0;
    }


    5.3.2 字符重排

         输入一个字典(用******结尾),然后再输入若干单词。每输入一个单词w,你都需要在字典中找出所有可以用w的字母重排后得到的单词,并按照字典序从小到大的顺序在一行中输出(如果不存在,输出:()。输入单词之间用空格或空行隔开,且所有输入单词都由不超过6个小写字母组成。注意,字典中的单词不一定按字典序排序。

         样例输入:

         tarp given score refund only trap work earn course pepper part

         ******

         resco nfudre aptr sett oresuc

         样例输出:

         score

         refund

         part trap tarp

         :(

         course

    代码:

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    int n;
    char word[2000][10],sorted[2000][10];
    //字符比较函数 
    int cmp_char(const void* _a,const void* _b)
    {
        char* a=(char*)_a;
        char* b=(char*)_b;
        return *a-*b;
    }
    //字符串比较函数 
    int cmp_string(const void* _a,const void* _b)
    {
        char* a=(char*)_a;
        char* b=(char*)_b;
        return strcmp(a,b);
    }
    
    int main()
    {
        n=0;
        for(;;)
        {
            scanf("%s",word[n]);
            if(word[n][0]=='*')
               break;//遇到结束标志就终止循环 
            n++;
        }
        qsort(word,n,sizeof(word[0]),cmp_string);//给所有单词排序 
        for(int i=0;i<n;i++)
        {
            strcpy(sorted[i],word[i]);
            qsort(sorted[i],strlen(sorted[i]),sizeof(char),cmp_char);//给每个单词排序 
        }
        
        char s[10];
        while(scanf("%s",s)==1)//持续读取到文件结尾 
        {
            qsort(s,strlen(s),sizeof(char),cmp_char);//给输入单词排序 
            int found=0;
            for(int i=0;i<n;i++)
               if(strcmp(sorted[i],s)==0)
               {
                   found=1;
                   printf("%s",word[i]);//输出原始单词,而不是排序后的 
               }
            if(!found)
              printf(":(");
              printf("
    ");
        }
        return 0;
    }

    5.4.1 Cantor的数表

         如下列数,第一项是1/1,第二项是1/2,第三项是2/1,第四项是3/1,第五项是2/2,……。输入n,输出第n项。

        1/1   1/2  1/3  1/4  1/5

        2/1   2/2  2/3  2/4

        3/1   3/2  3/3

        4/1   4/2

        5/1

       样例输入:

       3

       14

       7

       12345

       样例输出:

       2/1

       2/4

       1/4

       59/99

    分析:

          按照斜线分类,第一条斜线有一个数,第二条斜线有2个数……第i条有i个数。前i条斜线一共有S(k)=1+2+3+……+k=1/2*k*(k+1)个数。

         第k条斜线的倒数第i个元素是i/(k+1-i)。

    代码:

    //利用代数,避免浮点误差 
    #include<stdio.h>
    #include<math.h>
    int main()
    {
        int n;
        while(scanf("%d",&n)==1)
        {
            int k=(int)floor((sqrt(8.0*n+1)-1)/2-1e-9)+1;
            int s=k*(k+1)/2;
            printf("%d/%d
    ",s-n+1,k-s+n);
        }
        return 0;
    }

    5.4.2 因子和阶乘

        输入正整数n(2≤n≤100),把阶乘n!=1×2×3×……×n分解成素因子相乘的形式,从小到大输出各个素数(2、3、5……)的指数。

        例如825=3×52×11应表示成(0,1,2,0,1),表示分别有0、1、2、0、1个2、3、5、7、11.你的程序应忽略比最大素因子更大的素数(否则末尾会有无穷多个0)。

        样例输入:

        5

        53

        样例输出:

        5!= 3 1 1

        53! = 49 23 12 8 4 4 3 2 2 1 1 1 1 1 1 1

    代码:

    #include<stdio.h>
    #include<string.h>
    //素数判定,注意,n不能太大 
    int is_prime(int n)
    {
        for(int i=2;i*i<=n;i++)
           if(n%i==0)   return 0;
        return 1;
    }
    //素数表 
    int prime[100],count=0;
    int main()
    {
        //n和各个素数的指数 
        int n,p[100];
        
        //构造素数表 
        for(int i=2;i<=100;i++)
           if(is_prime(i))
               prime[count++]=1;
        
        while(scanf("%d",&n)==1)
        {
            printf("%d!=",&n);
            memset(p,0,sizeof(p));
            int maxp=0;
            for(int i=1;i<=n;i++)
            {
                //必须把i复制到变量m中,而不要在做除法时直接修改它 
                int m=i;
                for(int j=0;j<count;j++)
                    while(m%prime[j]==0)//反复除以prime[j],并累加p[j] 
                    {
                        m/=prime[j];
                        p[j]++;
                        if(j>maxp)//更新更大素因子下标 
                           maxp=j;
                    }
            }
            //只循环到最大下标 
            for(int i=0;i<=maxp;i++)
               printf("%d",p[i]);
            printf("
    ");
        }
        return 0;
    }

    5.4.3果园里的树

    果园里的树排列成矩阵。它们的x,y坐标均是1~99的整数。输入若干个三角形,依次统计每一个三角形内部和边界上共有多少棵树

       样例输入:

       1.5 1.5        1.5 6.8        6.8 1.5

       10.7 6.9       8.5 1.5       14.5 1.5

       样例输出:

        15

        17

    分析:

      此处用到了三角形的有向面积

    代码:

    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    
    double area2(double x0,double y0,double x1,double y1,double x2,double y2)
    {
        return x0*y1+x2*y0+x1*y2-x2*y1-x0*y2-x1*y0;
    }
    
    int main()
    {
        double x0,y0,x1,y1,x2,y2;
        while(~scanf("%lf %lf %lf %lf %lf %lf",&x0,&y0,&x1,&y1,&x2,&y2))
        {
            printf("%d
    ",(int)fabs(area2(x0,y0,x1,y1,x2,y2))/2+1);
        }
        return 0;
    }                    
  • 相关阅读:
    基本样式
    表单基础知识
    边框内圆角
    灵活的背景定位
    多重边框
    半透明边框
    变量关系
    闭包2——闭包与变量
    闭包
    基本包装类型
  • 原文地址:https://www.cnblogs.com/lipching/p/3873212.html
Copyright © 2011-2022 走看看