东华大学2020考研计算机复试准备上机题解析答案_进阶篇(61-95)

前言

提交代码:
选择C++编程语言,因为有的时候会用到C++的一些方便的头文件什么的,还有我编写代码是有一部分是纯C的,因为做题来讲C的scanf和printf很方便。

发布文章安排:
我会抽时间发文章的,看时间安排了,现在时间有点紧吧。马上过年了。过完年要开始准备准备其他东西了

解题解法质量:
关于我的解法和代码的精简程度,我是以当时做题的心态来解题的,由于当时急着刷完所有题目,所以难免会有一些题应该有其他更优的解法,我却用了比较暴力一点的,毕竟当时的劳动强度有点大,抓进度来着,如果有更好的解法,欢迎联系我,或者直接评论,共同学习,共同进步!

联系方式:

如果有问题交流咨询,可以加入QQ群:673852347

其他未尽事宜,还望海涵!

61 螺旋方阵

作者: 孙辞海 时间限制: 1S 章节: 二维数组

问题描述 :

明明在上学的时候,参加数学兴趣班。在班上,老师介绍了一种非常有趣的方阵,称之为螺旋方阵。该方阵一共由n×n个正整数构成(我们称之为n阶螺旋方阵),即共有n行n列。

方阵中的数字从1开始递增,数字的排序规则是从左上角出发由1开始排序,并按顺时针方向旋进,即先排最外面的一圈,然后排里面的一圈,以此类推,直到排到最后一个数为止。

例如一个4阶的螺旋方阵,一共有4×4=16个正整数构成,数字从1递增到16,最后排出来的方阵如下:

1 2 3 4

12 13 14 5

11 16 15 6

10 9 8 7

明明回家后想自己动手构造这样的螺旋方阵。他从n=1开始构造,但是他发现当n越来越大时,螺旋方阵的复杂性就越高,然后构造出来的方阵就越容易出错。为了降低构造方阵的出错率,提高构造速度,明明就求助于你,请你帮他写一个程序,来构造螺旋方阵。 明明的问题可以归结为:给你一个正整数n,请你按题目描述中所述的方法,构造出n阶的螺旋方阵。

输入说明 :

你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据仅占一行,每行仅有一个正整数n(1≤n≤10),即所要构造的螺旋方阵的阶数。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。

输出说明 :

对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将这一组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果为一个n阶的螺旋方阵,方阵中的数字用一个空格隔开,具体形式请参考输出样例。每组运算结果与其后一组运算结果之间有一个空行,最后一组运算结果之后没有空行。 注:通常,显示屏为标准输出设备。

输入范例 :

9
4

输出范例 :

1 2 3 4 5 6 7 8 9
32 33 34 35 36 37 38 39 10
31 56 57 58 59 60 61 40 11
30 55 72 73 74 75 62 41 12
29 54 71 80 81 76 63 42 13
28 53 70 79 78 77 64 43 14
27 52 69 68 67 66 65 44 15
26 51 50 49 48 47 46 45 16
25 24 23 22 21 20 19 18 17

1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
#include<stdio.h>//:Q+_+Q: 2020:summershell
int main()//来了个简单的模拟题,哈哈哈
{
    int n,a[20][20],h=1;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)a[i][j]=0;
        if(h++!=1)printf("\n");
        //以第一个圈由n-1个数当边比较好,以此类推下一个圈的边是n-2个数
        int c=1,len=n-1,up,down,left,right;
        for(int i=1;i<=n/2;++i)
        {
            for(up=i;up<len+i;up++)a[i][up]=c++;//数len长度个数
            for(right=i;right<len+i;right++)a[right][up]=c++;//数len长度个数
            for(down=right;down>i;--down)a[right][down]=c++;
            for(left=right;left>i;--left)a[left][down]=c++;
            len-=2;
        }
        if(n%2==1)a[(n+1)/2][(n+1)/2]=c;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
                printf(j==1?"%d":" %d",a[i][j]);
            printf("\n");
        }
    }
    return 0;
}

62 方块转换

作者: xxx 时间限制: 1S 章节: 二维数组

问题描述 :

一块N x N(1=<N<=10)正方形的黑白瓦片的图案要被转换成新的正方形图案。
写一个程序来找出将原始图案按照以下列转换方法转换成新图案的最小方式:
#1:转90度:图案按顺时针转90度。
#2:转180度:图案按顺时针转180度。
#3:转270度:图案按顺时针转270度。
#4:反射:图案在水平方向翻转(形成原图案的镜像)。
#5:组合:图案在水平方向翻转,然后按照#1-#3之一转换。
#6:不改变:原图案不改变。
#7:无效转换:无法用以上方法得到新图案。
如果有多种可用的转换方法,请选择序号最小的那个。
比如:
转换前:
 @-@
 ---
 @@-
转换后:
 @-@
 @--
 --@
这种转换采取#1(按顺时针转90度)即可。
注意:图案中的字符“@”和“-”在转90度后,还是“@”和“-”。不要认为“-”转90度后变成“|”。

输入说明 :
第一行: 单独的一个整数N。
第二行到第N+1行: N行,每行N个字符(不是’@‘就是’-‘);这是转换前的正方形。
第N+2行到第2*N+1行: N行,每行N个字符(不是’@‘就是’-');这是转换后的正方形。
输出说明 :
单独的一行包括1到7之间的一个数字(在上文已描述)表明需要将转换前的正方形变为转换后的正方形的转换方法。

我的AC代码:
这个提交了好几次了。唉

#include<stdio.h>//:Q+_+Q: 2020 :summershell
//怎么说呢?为啥要给七种变换,太复杂了吧.case给的不好,每行前面有空格,这一点需要注意一下
//我的天,全给我WA了,难道还得把空格算上???????
int f1(char str1[][20],char str2[][20],int n)
{//1,1--1,3 1,2-->2,3 1,3-->3,3 2,1-->1,2 2,2-->2,2 2,3-->3,2 3,1-->1,1 3,2-->2,1 3,3-->3,1
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)
            if(str1[i][j]!=str2[j][n+1-i])return 0;
    return 1;
}
int f2(char str1[][20],char str2[][20],int n)
{//1,1-->3,3 1,2-->3,2 1,3-->3,1 2,1-->2,3 2,2-->2,2 2,3-->2,1 3,1-->1,3 3,2-->1,2 3,3-->1,1
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)
            if(str1[i][j]!=str2[n+1-i][n+1-j])return 0;
    return 1;
}
int f3(char str1[][20],char str2[][20],int n)
{//相当于倒转90度 1,1-->3,1 1,2-->2,1 1,3-->1,1
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)
            if(str1[i][j]!=str2[n+1-j][i])return 0;
    return 1;
}
int f4(char str1[][20],char str2[][20],int n)
{//1,1-->1,3 1,2-->1,2 1,3-->1,1
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)
            if(str1[i][j]!=str2[i][n+1-j])return 0;
    return 1;
}
int f5(char str1[][20],char str2[][20],int n)
{
    char str3[20][20];
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)
            str3[i][j]=str1[i][n+1-j];
    if(f1(str3,str2,n)||f2(str3,str2,n)||f3(str3,str2,n))return 1;
    else return 0;
}
int f6(char str1[][20],char str2[][20],int n)
{
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)
            if(str1[i][j]!=str2[i][j])return 0;
    return 1;
}
void judge(char str1[][20],char str2[][20],int n)
{
    if( f1(str1,str2,n) )printf("1\n");
    else if(f2(str1,str2,n))printf("2\n");
    else if(f3(str1,str2,n))printf("3\n");
    else if(f4(str1,str2,n))printf("4\n");
    else if(f5(str1,str2,n))printf("5\n");
    else if(f6(str1,str2,n))printf("6\n");
    else printf("7\n");
}
int main()
{
    int n;
    char str1[20][20],str2[20][20];
    while(scanf("%d ",&n)!=EOF)
    {
        for(int i=1;i<=n;++i)
        {
            scanf(" ");
            for(int j=1;j<=n;++j)scanf("%c",&str1[i][j]);
        }
        for(int i=1;i<=n;++i)
        {
            scanf(" ");
            for(int j=1;j<=n;++j)scanf("%c",&str2[i][j]);
        }
        judge(str1,str2,n);
    }
    return 0;
}

63 阵列

作者: 孙辞海 时间限制: 10S 章节: 二维数组

问题描述 :
明明在上学的时候,参加数学兴趣班。在班上,老师介绍了一种非常有趣的阵列。
该阵列由n个正整数构成,阵列中的数字从1开始递增,数字的排序规则是从1开始由中间逆时针向外转出,2出现在1的下面,然后直至输出n为止。

例如当n=5的时候,阵列如下:  
  5
1 4
2 3
当n=9时,阵列如下:
7 6 5
8 1 4
9 2 3
当n=10时,阵列如下:
  7 6 5
  8 1 4
  9 2 3
10

明明回家后想自己动手构造这样的阵列。他从n=1开始构造,但是他发现当n越来越大时,阵列的复杂性就越高,然后构造出来的阵列就越容易出错。为了降低构造阵列的出错率,提高构造速度,明明就求助于你,请你帮他写一个程序,来构造这样的阵列。
明明的问题可以归结为:给你一个正整数n,请你按题目描述中所述的方法,构造出阵列。
输入说明 :
你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据仅占一行,每行仅有一个正整数n(1≤n≤99),即所要构造的阵列的大小。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。
输出说明 :
对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将这一组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果为一个大小为n的阵列,阵列中的数字用一个空格隔开,具体形式请参考输出样例: 当n为个位数时,输出的每个数占1位,当n为两位数时,两位数所在的列输出的每个数占2位(不足2位的左边补空格)。 每组运算结果与其后一组运算结果之间有一个空行,最后一组运算结果之后没有任何空行。 注:通常,显示屏为标准输出设备。

 
#include<stdio.h>//:Q+_+Q: 2020 :summershell
#include<string.h>
int main()
{
//    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    int n,c=1,a[20][20];
    while(scanf("%d",&n)!=EOF)
    {
        memset(a,0,sizeof(a));
        if(c++!=1)printf("\n");
        int t=1,c=1,x,y;
        while(t*t<n)t+=2;//t确定是几阶的size
        x=(t+1)/2,y=(t+1)/2;
        a[x][y]=c++;//第一圈已经定了
        for(int i=2,j,len=2;i<=(t+1)/2&&c<=n;++i,len+=2)//一共几个圈
        {
            x++;//一圈的开始,然后绕一圈
            for(j=y;j<y+len&&c<=n;++j)a[x][j]=c++;//y+len/y-len是最终的界限
            y=j-1;x--;
            for(j=x;j>x-len&&c<=n;--j)a[j][y]=c++;
            x=j+1;y--;
            for(j=y;j>y-len&&c<=n;--j)a[x][j]=c++;
            y=j+1;x++;
            for(j=x;j<x+len&&c<=n;++j)a[j][y]=c++;
            x=j-1;
        }
        int ie,is,js,je,f;//防止多余的空格输出啊,确定第几行几列开始结束
        for(js=1;js<=t;js++)
        {
            for(f=1;f<=t;f++)if(a[f][js])break;
            if(f<=t)break;
        }

        for(je=t;je>0;je--)
        {
            for(f=1;f<=t;++f)if(a[f][je])break;
            if(f<=t)break;
        }
        for(is=1;is<=t;is++)
        {
            for(f=1;f<=t;++f)if(a[is][f])break;
            if(f<=t)break;
        }
        for(ie=t;ie>0;ie--)
        {
            for(f=1;f<=t;++f)if(a[ie][f])break;
            if(f<=t)break;
        }
 //       printf("%d--%d--%d--%d\n",is,ie,js,je);
        for(int i=is;i<=ie;i++)
        {
            for(int j=js;j<=je;++j)
            {
                if(i==ie&&j!=js&&a[i][j]==0)break;//这题的输出格式控制好烦啊
                if(j==je&&a[i][j]==0)break;
                if(j!=js)printf(" ");
                //当n为两位数时,两位数所在的列输出的每个数占2位,真是麻烦死人了。
                if(n>=12)printf(a[i][j]?"%2d":"  ",a[i][j]);
                if(n<=9)printf(a[i][j]?"%d":" ",a[i][j]);
                if(n==10)
                {
                    if(a[i][j]<=9 && a[i][j]>=7)printf(a[i][j]?"%2d":"  ",a[i][j]);
                    else printf(a[i][j]?"%d":" ",a[i][j]);
                }
                if(n==11)
                {
                    if(a[i][j]<=5 && a[i][j]>=3)printf(a[i][j]?"%d":" ",a[i][j]);
                    else printf(a[i][j]?"%2d":"  ",a[i][j]);
                }
            }
            printf("\n");
        }
    }
    return 0;
}

如果有问题交流咨询,可以加入QQ群:673852347

64 饲料调配

作者: xxx 时间限制: 2S 章节: 二维数组

问题描述 :
农夫约翰从来只用调配得最好的饲料来为他的奶牛。
饲料用三种原料调配成:大麦,燕麦和小麦。他知道自己的饲料精确的配比,在市场上是买不到这样的饲料的。他只好购买其他三种混合饲料(同样都由三种麦子组成),然后将它们混合,来调配他的完美饲料。
给出三组整数,表示 大麦:燕麦:小麦 的比例,找出用这三种饲料调配 x:y:z 的饲料的方法。
例如,给出目标饲料 3:4:5 和三种饲料的比例:
1:2:3
3:7:1
2:1:2
你必须编程找出使这三种饲料用量最少的方案,要是不能用这三种饲料调配目标饲料,输出’NONE’。‘用量最少’意味着三种饲料的用量(整数)的和必须最小。
对于上面的例子,你可以用8份饲料1,2份饲料2,和5份饲料3,来得到7份目标饲料: 8*(1:2:3) + 1*(3:7:1) + 5*(2:1:2) = (21:28:35) = 7*(3:4:5)
以上数字中,表示饲料比例的整数都是小于100(数量级)的非负整数,表示各种饲料的份数的整数都小于100。一种混合物的比例不会由其他混合物的比例直接相加得到。
输入说明 :
Line 1: 三个用空格分开的整数,表示目标饲料
Line 2…4: 每行包括三个用空格分开的整数,表示农夫约翰买进的饲料的比例
输出说明 :
输出文件要包括一行,这一行要么有四个整数,要么是’NONE’。前三个整数表示三种饲料的份数,用这样的配比可以得到目标饲料。第四个整数表示混合前三种饲料后得到的目标饲料的份数。

#include<stdio.h>//:Q+_+Q: 2020 :summershell
int main()//让我想起了中学的化学方程式配平问题了,暴力枚举
{
 //   freopen("in.txt","r",stdin);
 //   freopen("out.txt","w",stdout);
    int a[20][20];
    while(scanf("%d %d %d ",&a[0][0],&a[0][1],&a[0][2])!=EOF)
    {//题上没说最后的比例不会含有0
        for(int i=1;i<=3;++i)
        scanf("%d %d %d ",&a[i][0],&a[i][1],&a[i][2]);
        int flag=1;
        for(int i=0;i<101&&flag;++i)
        for(int j=0;j<101;++j)
        for(int k=0;k<101&&flag;++k)
        {
            int bili;
            int temp1=i*a[1][0]+j*a[2][0]+k*a[3][0],temp2=i*a[1][1]+j*a[2][1]+k*a[3][1],temp3=i*a[1][2]+j*a[2][2]+k*a[3][2];
            if(temp1&&a[0][0])bili=temp1/a[0][0];
            else if(temp2&&a[0][1])bili=temp2/a[0][1];
            else if(temp3&&a[0][2])bili=temp3/a[0][2];
            if(bili*a[0][0]==temp1 && bili*a[0][1]==temp2 && temp3==bili*a[0][2] && (i+j+k))//不全为0才可以
                {
                    printf("%d %d %d %d\n",i,j,k,bili);
                    flag=0;
                }
        }
        if(flag)printf("NONE\n");
    }
    return 0;
}

如果有问题交流咨询,可以加入QQ群:673852347

65 乒乓球

作者: ZhouMingLiang 时间限制: 10S 章节: 字符串

问题描述 :
国际乒联主席沙拉拉自从上任以来就立志于推行一系列改革,以推动乒乓球运动在全球的普及。其中11分制改革引起了很大的争议,有一部分球员因为无法适应新规则只能选择退役。明明就是其中一位,他退役之后走上了乒乓球研究工作,意图弄明白11分制和21分制对选手的不同影响。在开展他的研究之前,明明首先需要对他多年比赛的统计数据进行一些分析,所以需要你的帮忙。 (注:11(21)分制,在一局比赛中,选手A先得到11(21)分且此时领先选手B 2分或2分以上时,则选手A赢得此局;若当双方打成10(20)平后,则先多得2分的一方为胜方,赢得此局。)
明明通过以下方式进行分析,首先将比赛每个球的胜负列成一张表,然后分别计算在11分制和21分制下,双方的比赛结果(截至记录末尾)。一局比赛的开始比分为0比0。 比如现在有这么一份记录,(其中W表示明明获得一分,L表示明明的对手获得一分):

WWWWWWWWWWWWWWWWWWWWWWLW 

在11分制下,此时比赛的结果是明明第一局11比0获胜,第二局11比0获胜,正在进行第三局,当前比分1比1。
在21分制下,此时比赛结果是明明第一局21比0获胜,正在进行第二局,当前比分2比1。
再如有这么一份记录,(其中W表示明明获得一分,L表示明明的对手获得一分):

WLWLWLWLWLWLWLWLWLWLWLWLWL 

在11分制下,此时比赛的结果是明明和对手打成13比13,这局比赛仍没有分出胜负,因为任何一方都没有领先其对手2分。
在21分制下,此时比赛的结果是明明和对手打成13比13,这局比赛仍在进行中。
由于明明参加过多年的比赛,比赛的数据量相当庞大,如果仅仅使用手工统计,在短时间内统计出结果对于明明来说是相当困难的。因此明明求助于你,希望你能写一个程序,帮助他快速地统计出结果来。
明明的问题可以归结为:给你一系列的比赛数据(WL形式),分别按照11分制和21分制的比赛规则进行统计,然后输出统计结果。
输入说明 :
你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每行包括一串有W、L和E组成比赛结果,其中W表示明明得一分,L表示明明的对手得一分,E表示该组测试数据的结束,也就是说E后面的W、L应该忽略,无需处理。每行的长度不会超过30个字符。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。
输出说明 :
对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将每组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。
每组运算结果由两部分组成,其中第一部分是11分制下的结果,第二部分是21分制下的结果,两部分之间由一个空行分隔。
每部分由若干行组成,每一行对应一局比赛的比分(按比赛信息输入顺序),每局的比分按如下形式表示:m:n,其中m表示明明的得分,n表示明明的对手的得分,m、n之间用一个冒号隔开。
输出时,每组运算结果与其后一组运算结果之间有一个空行,第一组运算结果前面以及最后一组运算结果后面没有任何空行或其他任何字符。 注:通常,显示屏为标准输出设备。

#include<stdio.h>//:Q+_+Q: 2020 :summershell
#include<string.h>
int main()//紧扣题目的判胜条件
{
 //   freopen("in.txt","r",stdin);
   // freopen("out.txt","w",stdout);
    char str[2020],s[100];
    int cou=1;
    while(gets(s)!=NULL)
    {
        if(cou++!=1)printf("\n");
        int len,flag=1,c=0;
        while(flag)
        {
            len=strlen(s);
            for(int i=0;i<len&&flag;++i)
                if(s[i]!='E')str[c++]=s[i];
            else flag=0;
            if(flag)gets(s);
        }
        str[c]='\0';
        int m=0,n=0;
        for(int i=0;i<c;i++)//11分制下的
        {
            if(str[i]=='W')m++;
            else n++;
            if((m==11&&m-n>=2)||(n==11&&n-m>=2))//m赢了
            {
                printf("%d:%d\n",m,n);
                m=n=0;
            }
            int j=i;
            if(m==10 && n==10)//如果10平
            {
                int tm=0,tn=0;
                for(j=i+1;j<c;++j)
                {
                    if(str[j]=='W')tm++;
                    else tn++;
                    if(tn-tm>=2 || tm-tn>=2){m=m+tm,n=n+tn;break;}
                }
                if(j<c)
                {
                    printf("%d:%d\n",m,n);
                    m=n=0;
                }
            }
            i=j;//保持平衡
        }
        if(m+n)//若剩余的没打完
        {
            printf("%d:%d\n",m,n);
            m=n=0;
        }
        printf("\n");//两部分空行隔开
        for(int i=0;i<c;i++)//21分制下的
        {
            if(str[i]=='W')m++;
            else n++;
            if((m==21&&m-n>=2)||(n==21&&n-m>=2))//m/n赢了
            {
                printf("%d:%d\n",m,n);
                m=n=0;
            }
            int j=i;
            if(m==20 && n==20)//如果10平
            {
                int tm=0,tn=0;
                for(j=i+1;j<c;++j)
                {
                    if(str[j]=='W')tm++;
                    else tn++;
                    if(tn-tm>=2 || tm-tn>=2){m=m+tm,n=n+tn;break;}
                }
                if(j<c)
                {
                    printf("%d:%d\n",m,n);
                    m=n=0;
                }
            }
            i=j;//保持平衡
        }
        if(m+n)//若剩余的没打完
        {
            printf("%d:%d\n",m,n);
            m=n=0;
        }
    }
    return 0;
}

如果有问题交流咨询,可以加入QQ群:673852347

66 字符串统计

作者: SunCiHai 时间限制: 10S 章节: 字符串

问题描述 :
明明最近在做一个有关字符串的统计工作。两个由小写字母组成的字符串s1和s2,明明需要统计出以下四种关系:
(1)在s1或s2中存在的字母(包括在s1和s2中都存在的字母);
(2)在s1中且在s2中的字母;
(3)在s1中但不在s2中的字母,在s2中但不在s1中的字母;
(4)不在s1中且也不在s2中的字母;
例如两个字符串s1为“lkjsvoahs”,s2为“qglhskjdfg”:
(1)在s1或者在s2或者s1、s2中都存在的字母:adfghjkloqsv;
(2)在s1中且在s2中的字母:hjkls;
(3)在s1中但不在s2中的字母,在s2中但不在s1中的字母:adfgoqv;
(4)不在s1中且也不在s2中的字母:bceimnprtuwxyz;
明明统计了很久,但是由于统计过程十分繁琐,且很容易出错,导致明明的进度非常慢,很有可能因为统计不完而错过了晚上的约会。因此明明想请你帮个忙,帮他写一个程序,用程序来统计出以上几项内容。
明明的问题可以归结为:
输入两串由小写字母组成的字符串s1和s2,比较其中的字母,输出以下四项,输出的字母以字典顺序排列:
(1)在s1或s2中存在的字母(包括在s1和s2中都存在的字母);
(2)在s1中且在s2中的字母;
(3)在s1中但不在s2中的字母,在s2中但不在s1中的字母;
(4)不在s1中且也不在s2中的字母;
例如字符串s1为sadf,s2为asdf,则需输出以下四行(注意输出的格式):
in s1 or s2:adfs
in s1 and s2:adfs
in s1 but not in s2 ,or in s2 but not in s1:
not in s1 and s2:bceghijklmnopqrtuvwxyz

输入说明 :
你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据两行,每组测试数据的第一行为字符串s1,每组测试数据的第二行为字符串s2;s1和s2都由小写英文字母组成,且长度不超过26个字符。测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。
输出说明 :
对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将这一组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。
每组运算结果由四行组成:
第一行为在s1或者在s2或者s1、s2中都存在的字母;
第二行为在s1中且在s2中的字母;
第三行为在s1中但不在s2中的字母,在s2中但不在s1中的字母;
第四行为不在s1中且也不在s2中的字母;
具体格式请参考样例输出。
每组运算结果其行首和行尾都没有任何空格,每组运算结果与其后一组运算结果之间有一个空行,最后一组运算结果后面没有空行。
注:通常,显示屏为标准输出设备。

#include<stdio.h>// summershell
#include<string.h>
int main()//直接写吧,没啥套路。水题一枚
{
 //   freopen("in.txt","r",stdin);
   // freopen("out.txt","w",stdout);
    char str1[2020],str2[2020];
    int cou=1,alpha1[26],alpha2[26];
    while(gets(str1)!=NULL)
    {
        gets(str2);
        if(cou++!=1)printf("\n");
        memset(alpha1,0,sizeof(alpha1));
        memset(alpha2,0,sizeof(alpha2));
        int len1=strlen(str1),len2=strlen(str2);
        for(int i=0;i<len1;++i)alpha1[str1[i]-'a']++;
        for(int i=0;i<len2;++i)alpha2[str2[i]-'a']++;
        printf("in s1 or s2:");
        for(int i=0;i<26;++i)if(alpha1[i]||alpha2[i])printf("%c",i+'a');
        printf("\n");
        printf("in s1 and s2:");
        for(int i=0;i<26;++i)if(alpha1[i]&&alpha2[i])printf("%c",i+'a');
        printf("\n");
        printf("in s1 but not in s2 ,or in s2 but not in s1:");
        for(int i=0;i<26;++i)if((alpha1[i]&&!alpha2[i])||(alpha2[i]&&!alpha1[i]))printf("%c",i+'a');
        printf("\n");
        printf("not in s1 and s2:");
        for(int i=0;i<26;++i)if(!alpha1[i]&&!alpha2[i])printf("%c",i+'a');
        printf("\n");

    }
    return 0;
}

如果有问题交流咨询,可以加入QQ群:673852347

67 求字符串的起始位置

作者: SunCiHai 时间限制: 10S 章节: 字符串

问题描述 :
在程序设计中,对字符串的处理是经常遇到的一个问题。
例如,将字符串中所有的英文字母变成大写,或者将一个字符串与另一个字符串连接构成一个新的字符串。
由于此类的操作非常普遍,因此,在设计程序语言的时候,设计者就已经把这类操作的代码写好了,如果编程人员要使用这些代码,只需把该类代码的头文件包含到自己的程序中,编程人员就可以很简单的调用,这样使编程节省了不少时间。
明明是一名项目经理,他现在负责一种新的程序设计语言的开发,现在需要预先实现大量的和处理字符串有关的功能方法,以后这些方法会包含到程序设计语言中,方便程序语言使用者的开发。你是明明手下的一名软件工程师,明明分配给你一个任务,在两个字符串中,找到一个字符串在另一个字符串中的起始位置。 例如,有两个字符串,一个字符串s= “abc”,另一个字符串subs=“bc”,现在就要找出“bc”在“abc”中的其实位置,在这个例子中,“bc”的起始位置为2。
明明的问题可以归结为:输入两串字符串s和subs,求s中subs的起始位置。
输入说明 :
你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据两行,每组测试数据的第一行为字符串s,s的长度小于100,每组测试数据的第二行为字符串subs,subs的长度小于100,s和subs中仅包含小写字母和数字。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。
输出说明 :
对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将这一组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果为一个整数m,即subs在s中的起始位置,如果在s中找不到subs这个子串,则m=0。每组运算结果单独形成一行数据,其行首和行尾都没有任何空格,每组运算结果与其后一组运算结果之间没有任何空行,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行。 注:通常,显示屏为标准输出设备。

#include<stdio.h>// summershell
#include<string.h>
int findsub(char s1[],char s2[])//看吧,很简单,对不对
{
    int len1=strlen(s1),len2=strlen(s2);
    for(int i=0,j;i<len1;++i)
    {
        if(s1[i]==s2[0])
        {
            for(j=1;j<len2;++j)
                if(s1[i+j]!=s2[j])break;
            if(j>=len2)return i+1;
        }
    }
    return 0;
}
int main()//没让写kmp已经很仁慈了,开始吧
{
 //   freopen("in.txt","r",stdin);
   // freopen("out.txt","w",stdout);
    char str[2020],subs[2020];
    while(gets(str)!=NULL)
    {
        gets(subs);
        printf("%d\n",findsub(str,subs));
    }
    return 0;
}

68 最长的单词

作者: ZhuKai 时间限制: 10S 章节: 字符串

问题描述 :
明明刚开始学习英语的时候,对英语有浓厚的兴趣,但是随着时间的推移,英语单词量的增加,明明越来越觉得背单词是一件相当痛苦的事情。于是他想出各种各样的方法来增加背单词的乐趣。
这次他想出的方法是把所有要背的英语单词排成一行,找出其中最长的一个单词来先背,然后划去这个单词,在剩下的单词中再找出一个最长的单词来背,以此类推,直到把所有单词都背完。如果有多个长度相同的单词,则先背一行中靠前的那个单词。这样做的好处是:背到越后面,单词越短,越容易背,越能增加背单词的信心。
例如有这么一行单词: one two three four five 明明会首先挑出three来背,因为它是最长的一个单词,由5个字母组成;然后明明会选择four这个单词,虽然five这个单词的长度和four这个单词的长度一样,但是four在five的前面,所以明明会先背four这个单词,然后再背five,等明明把five这个单词背完以后,接着背one这个单词,最后背的是two这个单词。
但是在这样背单词之中,明明又发现了另一个问题,当要背非常多的单词时,寻找最长的单词会花很多时间,他想让你帮助他写一个程序,找出一行单词中最长的那个,节约明明背单词所花的时间,与此同时,明明希望你能告诉他这个英文单词有多少个字母组成,那他可以做到心里有数。
明明的问题可以归结为:在一行英文单词中,找出其中最长的单词(若有多个最长,找出第一个出现的),并输出这个单词的长度。
输入说明 :
你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据仅占一行,每行包括许多个英语单词和空格,单词和单词之间可能有多个空格,每行的长度不会超过1000个字符。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。
输出说明 :
对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将每组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果为一个整数和一个英语单词,整数表示该英文单词的长度,整数和单词之间用一个空格隔开。输出时,每组运算结果单独占一行,其行首和行尾都没有任何空格或其他任何字符,每组运算结果与其后一组运算结果之间没有任何空行或其他任何字符,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行或其他任何字符。 注:通常,显示屏为标准输出设备。

#include<stdio.h>// summershell
#include<string.h>//考排序的吧
#include<stdlib.h>
int cmp(const void *a,const void *b)
{
    char *x=(char *)a,*y=(char *)b;
    int len1=strlen(x),len2=strlen(y);
    if(len1!=len2)
    return len2-len1;
    else return (&b)-(&a);//否则就按内存地址排序,还不知道能不能A,第一次这样做QAQ,祝我好运吧
}
int main()
{
    char s[2020],words[2020][100];
    while(gets(s)!=NULL)
    {
        memset(words,0,sizeof(words));
        int len=strlen(s),cou=0;//cou单词数
        for(int i=0,t=0;i<len;++i)
            if(s[i]!=' ')words[cou][t++]=s[i];
            else {cou++;t=0;}
        qsort(words,cou+1,sizeof(words[0]),cmp);//最后一个单词后面无空格,不可忽视
        printf("%d %s\n",strlen(words[0]),words[0]);
    }
    return 0;
}

如果有问题交流咨询,可以加入QQ群:673852347

69 奖学金

作者: ZhuKai 时间限制: 10S 章节: 字符串

问题描述 :
明明所在学校的惯例是在每学期的期末考试之后发放奖学金。
发放的奖学金共有五种,获取的条件各不相同:

  1. 院士奖学金:每人8000元,期末平均成绩高于80分,并且在本学期内发表1篇或1篇以上论文的学生均可获得。
  2. 五四奖学金:每人4000元,期末平均成绩高于85分,并且班级评议成绩高于80分的学生均可获得。
  3. 成绩优秀奖:每人2000元,期末平均成绩高于90分的学生均可获得。
  4. 西部奖学金:每人1000元,期末平均成绩高于85分的西部省份学生均可获得。
  5. 班级贡献奖:每人850元,班级评议成绩高于80分的学生干部均可获得。
    只要符合条件就可以得奖。 每项奖学金的获奖人数没有限制,每名学生也可以同时获得多项奖学金。
    例如明明的期末平均成绩是87分,班级评议成绩82分,同时他还是一位学生干部,那么他可以同时获得五四奖学金和班级贡献奖,奖金总数是4850元。
    由于老师在学期末的时候很忙,所以,他把奖学金统计的事情交给明明做。老师把考试的相关数据给了明明,让他统计出以下数据:
    1) 哪位同学获得的奖学金最多;
    2) 获得最多奖学金的同学一共获得了多少奖学金;
    3) 所有获得奖学金的同学一共获得了多少奖学金;
    明明虽然很愿意帮老师这个忙,但是他发现,同学的数量很多,统计起来很麻烦,经常有统计出错的情况发生。于是明明就想请你帮一个忙,帮他写一个统计程序,统计出以上三项内容。
    输入说明 :
    你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据有多行,每组测试数据的第一行有一个整数N(1≤N≤100),表示学生的总数。接下来的N行,每行是一位学生的数据,一行中从左向右依次是姓名,期末平均成绩,班级评议成绩,是否是学生干部,是否是西部省份学生,以及发表的论文数。姓名是由大小写英文字母组成的长度不超过20的字符串(不含空格),期末平均成绩和班级评议成绩都是0到100之间的整数(包括0和100),是否是学生干部和是否是西部省份学生分别用一个字符表示,Y表示是,N表示不是,发表的论文数是0到10的一个整数(包括0和10),每两个相邻数据项之间用一个空格分隔。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。
    输出说明 :
    对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将每组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。
    每组运算结果有三行,第一行是获得最多奖金的学生的姓名,第二行是这名学生获得的奖金总数。 如果有不止一名学生获得的奖学金最多,输出他们之中出现最早的学生姓名,第三行是这N个学生获得的奖学金的总数。输出时,每组运算结果其行首和行尾都没有任何空格或其他任何字符,每组运算结果与其后一组运算结果之间有一个空行,最后一组运算结果后面没有空行。 注:通常,显示屏为标准输出设备。
#include<stdio.h>// summershell
struct node
{
    char name[2020],GB,XB;
    int QM,BJ,LW,Bonus;
}stu[2020];
int main()//不是水题吗?怎么最后一个点过不去
{
    int n,c=1;
    while(scanf("%d",&n)!=EOF)
    {
        if(c++!=1)printf("\n");
        int SumBonus=0,maxnum=0;
        for(int i=0;i<n;++i)
        {
            scanf("%s %d %d %c %c %d",stu[i].name,&stu[i].QM,&stu[i].BJ,&stu[i].GB,&stu[i].XB,&stu[i].LW);
            stu[i].Bonus=0;
            if(stu[i].QM>80&&stu[i].LW)stu[i].Bonus+=8000;
            if(stu[i].QM>85&&stu[i].BJ>80)stu[i].Bonus+=4000;
            if(stu[i].QM>90)stu[i].Bonus+=2000;
            if(stu[i].QM>85&&stu[i].XB=='Y')stu[i].Bonus+=1000;
            if(stu[i].BJ>80&&stu[i].GB=='Y')stu[i].Bonus+=850;
            SumBonus+=stu[i].Bonus;
            if(stu[maxnum].Bonus<stu[i].Bonus)maxnum=i;
        }
        printf("%s\n%d\n%d\n",stu[maxnum].name,stu[maxnum].Bonus,SumBonus);
    }
    return 0;
}/*鉴于94题的前车之鉴,我决定把name的长度调大一些,试一试能不能A,检查了好多次都觉得没啥逻辑错误啊*/

70 回文数2

作者: ZhuKai 时间限制: 10S 章节: 字符串

问题描述 :
有一天,明明正在做作业,发现了一组很有趣的数字,例如1、11、313等等。他发现这些数字都是左右对称的,即不论你把这些数字从左读到右还是从右读到左,读出来的数字都是一样的。于是明明就把这个发现告诉了他爸爸。明明的爸爸是一名数学家,对此类型数字早有研究。他对明明说:“这些是回文数,是一种特殊的数字,即这些数字的左右两边是对称的。例如:11左右两边对称,313左右也是对称的。” 明明觉得这很有趣,接着问他爸爸还有什么和这类回文数有关的有趣的东西。明明的爸爸就说:“你把这些回文数转换成二进制数,看看是不是也符合回文数的规则。”明明发现1的二进制数也是1,符合回文数的规则;11的二进制数是1011,不符合回文数的规则;33的回文数是100001,符合回文数的规则。明明就回答爸爸说:“1和33的二进制数符合回文数的规则,11的二进制数则不符合回文数的规则。” 明明爸爸很满意明明的回答,又给了明明很多十进制数,让他判断在这些数中哪些数既是十进制回文数又是二进制回文数。明明起先做起来很有意思,但是时间一长就失去了兴趣。他想请你帮个忙,帮他写一个程序,用来判断一个数,它的十进制数是回文数,且它的二进制数也是回文数。
明明的问题可以归结为:给你一个整数(十进制),判断该整数的十进制数和它的二进制数是否全为回文数。
输入说明 :
你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据仅有一行,每行有一个整数N(0 <= N <= 1000),表示要判断回文数的那个数。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。
输出说明 :
对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将每组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果为“Yes”或“No”,如果该数的十进制数和二进制数都是回文数,则输出“Yes”(不含双引号),否则输出“No”(不含双引号)。每组运算结果单独形成一行数据,其行首和行尾都没有任何空格,每组运算结果与其后一组运算结果之间没有任何空行,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行。 注:通常,显示屏为标准输出设备。

#include<stdio.h>// summershell
int huiwen10(int a)//10进制的利用栈判断回文
{
    int stack[100],top=-1,temp=a;
    while(temp)
    {
        stack[++top]=temp%10;
        temp/=10;
    }
    while(top!=-1)
    {
        if(stack[top--]!=a%10)return 0;
        a/=10;
    }
    return 1;
}
int huiwen2(int x)//先换成2进制
{
    int stack[52],top=-1;
    if(x==0)return 1;
    while(x)
    {
        stack[++top]=x%2;
        x/=2;
    }
    for(int i=0;i<=top/2;i++)
    {
        if(stack[i]!=stack[top-i])return 0;
    }
    return 1;
}
int main()
{
    int N;
    while(scanf("%d",&N)!=EOF)
        printf((huiwen10(N)&&huiwen2(N))?"Yes\n":"No\n");
    return 0;
}

如果有问题交流咨询,可以加入QQ群:673852347

71 加法器

作者: frankhuhu 时间限制: 10S 章节: 字符串

问题描述 :
明明读小学的时候,不喜欢数学,尤其是不喜欢做加法,一做加法就头疼,这样导致明明长大后数学依然不好,而且对数字产生了抵触心理。可是不巧的是,明明进了一家会计公司,每天都要计算很多数据,在这些计算中加法运算居多,而且这些加法不只是是两个数之间的加法,更有多个数的连加。 例如:1+2+3的正确答案是6。 这给明明造成了很大的麻烦。你是明明的好朋友,看到明明如此痛苦,就产生了帮助明明的想法。你想帮明明写一个程序,这个程序能计算一串正整数的连加,从而帮助明明摆脱数字的困扰。 明明的问题可以归结为:给你一串正整数的连加表达式,完成这个表达式的计算。
输入说明 :
你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据仅有一行,每行有一个表达式,表达式由正整数和加号(“+”)组成,不含其他任何符号,表达式中的数字小于等于30000,表达式的长度不超过1000,具体格式见输入样例。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。
输出说明 :
对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将每组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果为一个整数,即表达式的值。每组运算结果单独形成一行数据,其行首和行尾都没有任何空格,每组运算结果与其后一组运算结果之间没有任何空行,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行。 注:通常,显示屏为标准输出设备。

#include<stdio.h>// summershell
#include<string.h>
int main()//水题
{
    char s[2020];
    while(gets(s)!=NULL)
    {
        int len=strlen(s),temp=0,sum=0;
        for(int i=0;i<len;++i)
        {
            if(s[i]<='9'&&s[i]>='0')temp=temp*10+s[i]-'0';
            else {sum+=temp;temp=0;}
        }
        printf("%d\n",sum+temp);
    }
    return 0;
}

72 构造序列

作者: 孙辞海 时间限制: 10S 章节: 字符串

问题描述 :
序列是在数学世界中一种非常有趣的数字现象,它通过某一规则来产生数字,使数字变得有趣、变幻无穷。很多数学家对序列这种事物产生了浓厚的兴趣,花了很多时间对其进行研究,明明就是其中的一位。一天,他又在研究一种新的序列产生规则,该序列的规则如下:
1) 第1轮,写出两个1,即11;
2) 第2轮,在它们中间插入2,成为121;
3) 第3轮,在上面数中每两个相邻的和为3的数之间插入3,成为13231;
4) 以此类推下去,第n轮,在第n-1轮的数字的基础上,每两个相邻的和为n的数之间插入n。
明明根据这个规则开始构造序列。开始还觉得容易,但是越到后面,明明发现构造序列的计算量越来越大,计算难度也越来越高,计算速度也越来越慢。于是,明明就求助于你这位程序设计专家,能否帮他写一个程序,构造出序列的前9项,然后当明明需要知道序列中的哪一项的时,你就把那一项的数字告诉明明。
明明的问题可以归结为:根据题目描述中所描述的序列产生规则构造序列的前9项,然后告诉你一个正整数n,要求你输出序列的第n项。
输入说明 :
你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据仅占一行,每行仅包括一个正整数n(1≤n≤9),代表之后所要求的序列的第n项的值。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。
输出说明 :
对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将这一组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果为一个整数,即所要求的序列中那一项的数值,每组运算结果单独形成一行数据,其行首和行尾都没有任何空格,每组运算结果与其后一组运算结果之间没有任何空行,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行。 注:通常,显示屏为标准输出设备。

#include<stdio.h>// summershell
void movef(int num[],int len,int pos,int x)
{
    for(int i=len-1;i>pos;i--)num[i+1]=num[i];
    num[pos+1]=x;
}
int main()//水题
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        int num[2020]={1,1},len=2;
        for(int i=2;i<=n;i++)
        for(int j=0;j<len-1;++j)
        if(num[j]+num[j+1]==i)
        {
            movef(num,len,j,i);
            len++;
        }
        for(int i=0;i<len;++i)printf("%d",num[i]);
        printf("\n");
    }
    return 0;
}

73 纯粹合数

作者: 朱凯 时间限制: 10S 章节: 字符串

问题描述 :
明明的爸爸是一位数学家,明明受他爸爸的影响从小就喜欢数学,经常向他爸爸学习或请教数学问题。
一天,明明问他爸爸什么是合数,明明的爸爸回答说:“首先,合数都是大于1的整数,其次合数是除了1和其本身外,还能被至少一个其他自然数整除的数,例如‘4’这个数,它除了能被1和4整除外,还能被2整除,因此‘4’就是合数;但是‘3’就不是合数,因为3只能被1和3这两个数整除,因此‘3’不是合数。”
聪明的明明很快就理解了他爸爸的意思,于是又接着问他爸爸:“那什么又是纯粹合数呢?”明明的爸爸接着回答说:“一个合数,去掉最高位,剩下的数是0或仍是合数;再去掉剩下的数的最高位,剩下的数还是0或合数;这样反复,一直到最后剩下的一位数仍为0或合数;我们把这样的数称为纯粹合数。
例如‘100’这个数,它能被1、2、4、5、10、20、50、100整除,因此100是个合数,我们去掉它的最高位,剩下的数是0(其实剩下的应该是00,但是前置0对一个整数来说没有意义,因此前置0被舍去,就剩下个位数上的0),因此‘100’是一个纯粹合数。有趣的是,100是最小的一个三位纯粹合数。
再例如‘104’这个数,104能被1、2、8、13、26、52、104整除,所以104是个合数;我们去掉它的最高位后剩下4,4能被1、2、4整除,所以4也是合数,所以‘104’是一个纯粹合数。
但是‘101’就不是纯粹合数,因为‘101’只能被1和101这两个数整除。”
明明对他爸爸的回答很满意,于是自己动手从100开始寻找纯粹合数,他一共找到了100个纯粹合数,调皮的明明开始反过来考爸爸了,问他爸爸能否告诉他第2个大于等于100的纯粹合数是哪个?第3个大于等于100的纯粹合数又是哪个?……明明的爸爸被这个突如其来的问题给难住了,他无法立刻回答出来,于是请求你的帮助,帮助他回答明明的这个问题。
明明的问题可以归结为:根据一个正整数n,求出从100开始从小到大的第n个纯粹合数。
输入说明 :
你写的程序需要从标准输入设备(通常为键盘)中读入多组测试数据,每组测试数据仅占一行,每行仅包括一个正整数n(1 ≤ n ≤ 100)。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。
输出说明 :
对于每一组测试数据,你写的程序需要计算出一组相应的运算结果,并将每组运算结果依次写入到标准输出设备(通常为启动该程序的文本终端,例如Windows中的命令行终端)中。每组运算结果为一个整数,即从100开始从小到大的第n个纯粹合数。每组运算结果单独形成一行数据,其行首和行尾都没有任何空格,每组运算结果与其后一组运算结果之间没有任何空行,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行。

#include<stdio.h>// summershell
int pri[20200],ans[2020];
void prime()
{
    for(int i=0;i<2000;++i)pri[i]=1;
    pri[0]=0,pri[1]=1;//去掉1
    for(int i=2;i<2000;++i)
        if(pri[i])
        for(int j=i+i;j<2000;j+=i)pri[j]=0;
}
int main()//水题
{
    int n,cou=1;
    prime();
    for(int i=100;i<2000;++i)
        if(pri[i]==0)//是合数
        {
            int wei=1,temp=i;
            while(temp){wei*=10;temp/=10;}
            temp=i;
            while(pri[temp]==0&&wei)
            {
                temp=temp%wei;
                wei/=10;
            }
            if(!wei)ans[cou++]=i;
        }
    while(scanf("%d",&n)!=EOF)printf("%d\n",ans[n]);
    return 0;
}

如果有问题交流咨询,可以加入QQ群:673852347

74 找出质数

作者: SunCiHai 时间限制: 10S 章节: 字符串

问题描述 :
明明学习数学已经有一段时间了。一次老师在课上讲了什么叫质数。质数就是大于等于2且只能被1和其本身整除的整数。明明觉得这很简单,以为这很容易掌握,于是就不多做练习。明的爸爸发现了这个问题,他想让明明多做练习,把质数这个知识点掌握牢固。但是,他也知道只是求质数会很无聊,明明一定不愿意多做。于是他想出了一个游戏,这个游戏叫“找出质数”,就是给明明一个数字串,要叫明明在这个数字串中找出一个最大的子串,要求这个子串是一个质数。 但是由于明明还太小,他的计算能力有限,因此明明的爸爸认为,找出长度大于4个字符的质数对明明来说太困难了。于是他降低了要求,只需找出小于10,000的最长的质数子串即可。 例如:有一个数字串为17,最大的子串就应该是17,因为1不是质数,7虽然是质数,但是7的长度只有1,17也是质数,它的长度为2,因此最大的子串就是17。 明明觉得这个游戏很有趣,就高兴地做了起来,明明的爸爸出了很多个数字串,由于数字串太多,所以明明爸爸自己找出最长的子串也要花很多的时间,于是明明的爸爸想让你帮他一个忙,写一个程序,找出数字串中最长的质数子串。
明明爸爸的问题可以归结为:输入一串数字,找出其中最长的不超过4个字符的质数子串。若有多个答案,则找出其中数值最大的一个。
输入说明 :
你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据仅一行,每组测试数据为一个数字串,数字串的长度不超过20。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。
输出说明 :
对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将这一组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果为一个整数,即最长的不超过4个字符的质数子串(测试数据保证这个子串存在);若有多个答案,则输出其中数值最大的一个。每组运算结果单独形成一行数据,其行首和行尾都没有任何空格,每组运算结果与其后一组运算结果之间没有任何空行,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行。 注:通常,显示屏为标准输出设备。

#include<stdio.h>// summershell
#include<string.h>//开整
#include<algorithm>
int cmp(int a,int b)
{
    return a>b;
}
int prime[10000];
void find_prime()
{
    memset(prime,0,sizeof(prime));
    prime[0]=prime[1]=1;
    for(int i=2;i<10000;i++)
        if(prime[i]==0)
        for(int j=2*i;j<10000;j+=i)prime[j]=1;
}
int main()
{
    find_prime();
    int maxnum[20];
    char s[22];
    while(gets(s)!=NULL)
    {
        int i,j,counter=0;
        memset(maxnum,0,sizeof(maxnum));
        for(i=4;i>0;--i)//先从最大子串入手
        {
            int x=strlen(s)-i;//因为strlen返回unsigned int,-i后会ERROR
            for(j=0;j<=x;j++)
            {
                int temp=s[j]-'0';
                for(int k=j+1;k<j+i;k++)temp=10*temp+s[k]-'0';
                if(prime[temp]==0)maxnum[counter++]=temp;
            }
            if(counter)break;//找到相对较长的就可以了
        }
        std::sort(maxnum,maxnum+counter,cmp);//排序
        printf("%d\n",maxnum[0]);
    }
    return 0;
}

如果有问题交流咨询,可以加入QQ群:673852347

75 翻译字符串

作者: 程裕强 时间限制: 1S 章节: 字符串

问题描述 :
在现代战争中,情报战越来越显示出它的重要性,敌我双方都想方设法得到对方的情报,然后一举歼灭对方。然而,随着加密技术的出现,对情报进行加密变得越来越频繁,想破解敌方的情报也越来越难。明明是一名富有经验的情报工作人员,他的主要任务就是破解敌方的情报,从而得到对己方有利的信息。在一次破解情报任务中,明明再次成功地破解了敌方的情报。明明的破解方法如下:一串以‘@’为结束标志的字符串,从左至右对其进行翻译,若字符串中当前字符是整数n(0≤n≤9),则表示将后一个字符重复n+1次,不论后一个字符是否为数字,且后一个字符无需再次翻译;若当前字符非数字,则表示自己,无需翻译,直接输出即可。最后,输出翻译完的字符串。
例如字符串为:2d352d@,因为第一个字符为数字2,则将后一个字符d输出3次,而d则不需再翻译,然后翻译3,3也是一个数字,则将后一个字符5输出4次,而5则不需再翻译,然后翻译2,2也是一个数字,将后一个字符d输出3次,而d则不需再翻译,最后一个字符为@,表示自己,直接输出即可,最后的输出为:ddd 555 5dd d@;(注:在翻译时,‘@’当作字符处理。) 这样翻译字符串的方法虽然简单,但是由于敌方的文件巨大,仅仅靠手工翻译是很难在短时间内完成的。于是明明就求助于你这位程序专家,按照明明提供的破译方法写一个程序,帮助明明快速把敌方文件翻译完成。
明明的问题可以归结为:按照文中提供的破译情报的方法,对字符串进行翻译,然后输出翻译后的字符串。
输入说明 :
你写的程序要求从标准输入设备(通常,键盘为标准输入设备)中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据仅占一行,每行包含一个以‘@’为结束标志的字符串,字符串由数字、小写字母以及‘@’组成,中间不包含空格,字符串长度不大于10。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。
输出说明 :
对于每一组测试数据你写的程序要求计算出一组相应的运算结果,并将这一组运算结果作为你所写程序的输出数据依次写入到标准输出设备(通常,显示屏为标准输出设备)中。每组运算结果为经过翻译的字符串,字符串中的字符以三个为一组输出,每组字符之间用一个空格隔开。每组运算结果单独形成一行数据,其行首和行尾都没有任何空格,每组运算结果与其后一组运算结果之间没有任何空行,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行。

#include<stdio.h>// summershell
#include<string.h>
int len=0;
void print(char c,int t)
{
    for(int j=1;j<=t;++j)
    {
        if(len>=3)
        {
            printf(" ");
            len=0;
        }
        printf("%c",c);
        len++;
    }
}
int main()//水题
{
    char str[2020];
    while(gets(str)!=NULL)
    {
        len=0;
        for(int i=0;str[i-1]!='@';++i)
        {
            if(str[i]>='1'&&str[i]<='9'){print(str[i+1],1+str[i]-'0');++i;}
            else print(str[i],1);
        }
        printf("\n");
    }
    return 0;
}

76 分割数字并排序

作者: xxx 时间限制: 1S 章节: 字符串

问题描述 :
输入一行数字,如果我们把这行数字中的‘5’都看成空格,那么就得到一行用空格分割的若干非负整数(可能有些整数以‘0’开头,这些头部的‘0’应该被忽略掉,除非这个整数就是由若干个‘0’组成的,这时这个整数就是0)。
你的任务是:对这些分割得到的整数,依从小到大的顺序排序输出。

输入说明 :
输入包含多组测试用例,第一行,测试案例个数,每组输入数据只有一行数字(数字之间没有空格),这行数字的长度不大于1000。
输入数据保证:分割得到的非负整数不会大于100000000;输入数据不可能全由‘5’组成。

输出说明 :
对于每个测试用例,输出分割得到的整数排序的结果,相邻的两个整数之间用一个空格分开,每组输出占一行。

#include<stdio.h>// summershell
#include<string.h>
#include<algorithm>
int main()//水题
{
    char str[2020];
    int num[2020],t;
    scanf("%d ",&t);
    while(t--)
    {
        gets(str);
        int cou=0,len=strlen(str),temp=0;
        if(str[len-1]!='5')//末位加上5
        {str[len+1]=str[len];str[len]='5';len++;}
        for(int i=0;i<len;++i)
        {
            if(str[i]!='5')
            temp=temp*10+str[i]-'0';
            else if(str[i+1]!='5'){num[cou++]=temp;temp=0;}//可能出现两个5连起来
        }
        std::sort(num,num+cou);//排序,嘻嘻嘻
        for(int i=0;i<cou;++i)printf(i==0?"%d":" %d",num[i]);
        printf("\n");
    }
    return 0;
}

如果有问题交流咨询,可以加入QQ群:673852347

77 大实数加法

作者: xxx 时间限制: 1S 章节: 字符串

问题描述 :
给你两个正的实数A和B,你的任务是计算出A+B的值。

输入说明 :
本题目包含T组测试数据。
每一组测试数据在一行里面包含两个长度不大于400的正实数A和B,A和B均无多余的前导0。

输出说明 :
对于每一组测试数据,请在一行里面输出输出A+B的值,行首与行尾均无空格。
运算结果最后的0(比如1.400)不需要输出(输出为1.4)。

#include<stdio.h>// summershell
#include<string.h>
#include<algorithm>
char s1[2020],s2[2020],s1x[2020],s2x[2020],sZ[2020],sX[2020];
int lenZ1,lenZ2,lenX1,lenX2,lenZ,lenX;//分别是小数部分和整数部分的长度

int main()//和大整数一样的,不过小数部分和整数部分得分开处理了
{
  //  freopen("in.txt","r",stdin);
    int T,i,j;
    scanf("%d ",&T);
    while(T--)
    {
        scanf("%s %s",s1,s2);
        lenZ1=lenX1=lenZ2=lenX2=0;
        int dot=0,len1=strlen(s1),len2=strlen(s2),JW;//JW表示进位
        for(i=0;i<len1;++i)//将整数和小数部分分开
        {
            if(s1[i]=='.'){dot=1;continue;}//小数标志分开
            if(!dot)lenZ1++;
            else s1x[lenX1++]=s1[i];
        }
        s1[lenZ1]=s1x[lenX1]='\0';
        dot=0;
        for(i=0;i<len2;++i)
        {
            if(s2[i]=='.'){dot=1;continue;}
            if(!dot)lenZ2++;
            else s2x[lenX2++]=s2[i];
        }
        s2[lenZ2]=s2x[lenX2]='\0';
        //*********已经分割完毕
        //开始小数部分的加和
        i=std::max(lenX1-1,lenX2-1);//从最远的地方开始
        JW=0;
        lenX=0;
        while(i>=0)
        {
            int a,b,temp;
            if(i>=lenX1)a=0;
            else a=s1x[i]-'0';
            if(i>=lenX2)b=0;
            else b=s2x[i]-'0';
            temp=a+b+JW;
            JW=0;
            if(temp>9)JW=1,temp-=10;
            sX[lenX++]=temp+'0';
            --i;
        }//有可能还存在进位哦!
        sX[lenX]='\0';
        //开始整数部分的加和
        i=lenZ1-1,j=lenZ2-1;
        lenZ=0;
        while(i>=0&&j>=0)
        {
            int a,b,temp;
            a=s1[i]-'0';
            b=s2[j]-'0';
            temp=a+b+JW;
            JW=0;
            if(temp>9)JW=1,temp-=10;
            sZ[lenZ++]=temp+'0';
            --i;
            --j;
        }
        while(i>=0)//未完成
        {
            int a,temp;
            a=s1[i]-'0';
            temp=a+JW;
            JW=0;
            if(temp>9)JW=1,temp-=10;
            sZ[lenZ++]=temp+'0';
            i--;
        }
        while(j>=0)//未完成
        {
            int a,temp;
            a=s2[j]-'0';
            temp=a+JW;
            JW=0;
            if(temp>9)JW=1,temp-=10;
            sZ[lenZ++]=temp+'0';
            j--;
        }
        if(JW)//如果还存在进位怎么办
        sZ[lenZ++]=JW+'0';
        sZ[lenZ]='\0';
        //大业已毕,只需修改输出即可
        for(i=lenZ-1;i>=0;--i)printf("%c",sZ[i]);//整数部分输出了
        int flag=-1;//从后往前搜索小数部分非0的位置
        for(i=0;i<lenX;++i)if(sX[i]!='0'){flag=i;break;}
        if(flag!=-1)//存在小数才能输出哦
        {
            printf(".");
            for(i=lenX-1;i>=flag;--i)printf("%c",sX[i]);
        }
        printf("\n");
    }
    return 0;
}

如果有问题交流咨询,可以加入QQ群:673852347

78 A == B ?

作者: xxx 时间限制: 1S 章节: 字符串

问题描述 :
给你两个非负实数A和B,如果A等于B,输出 “YES”, 否则输出"NO"
输入说明 :
第一行N,表示有N组测试数据。
以下N行,每行两个非负实数 A和B。每个实数不超过1000位,且可能在前面和后面有0存在。

输出说明 :
对于每组测试数据,如果A和B相等则输出 “YES”, 否则输出 “NO”。
每组测试数据占一行,两组测试数据之间无空行。行首与行尾均无空格。

#include<stdio.h>// summershell
#include<string.h>
int judge(char s1[],char s2[],int c1,int c2)
{
    int i;
    for(i=0;i<c1&&i<c2;++i)
        if(s1[i]!=s2[i])return 0;
    if(i<c1)//若后面全0才行
    {
        while(i<c1)if(s1[i++]!='0')return 0;
    }
    if(i<c2)//若后面全0才行
    {
        while(i<c2)if(s2[i++]!='0')return 0;
    }
    return 1;
}
int main()//水题
{
    char str[2020],s1[2020],s2[2020];
    int t;
    scanf("%d ",&t);
    while(t--)
    {
        gets(str);
        int c1=0,c2=0,dot1=0,dot2=0,len=strlen(str),i;
        for(i=0;str[i]!=' ';i++)
        {
            if(str[i]!='0' || (str[i]=='0'&&c1))
                {s1[c1++]=str[i];}
            if(str[i]=='.')dot1=1;
        }
        if(dot1==0)s1[c1++]='.';//补个小数点
        for(i++;i<len;++i)
        {
            if(str[i]!='0' || (str[i]=='0'&&c2))
                {s2[c2++]=str[i];}
            if(str[i]=='.')dot2=1;
        }
        if(dot2==0)s2[c2++]='.';
        puts(judge(s1,s2,c1,c2)?"YES":"NO");
    }
    return 0;
}

如果有问题交流咨询,可以加入QQ群:673852347

79 母牛制造的回文

作者: xxx 时间限制: 1S 章节: 字符串

问题描述 :
据说如果你给无限只母牛和无限台巨型便携式电脑(有非常大的键盘),那么母牛们会制造出世上最棒的回文。你的工作就是去这些牛制造的奇观(最棒的回文)。在寻找回文时不用理睬那些标点符号、空格(但应该保留下来以便做为答案输出),只用考虑字母’A’-‘Z’和’a’-‘z’。要你寻找的最长的回文的文章是一个不超过20,000个字符的字符串。我们将保证最长的回文不会超过2,000个字符(在除去标点符号、空格之前)。
输入说明 :
一个不超过20,000个字符的文件。
输出说明 :
输出的第一行应该包括找到的最长的回文的长度。
下一个行或几行应该包括这个回文的原文(没有除去标点符号、空格), 把这个回文输出到一行或多行(如果回文中包括换行符)。如果有多个回文长度都等于最大值,输出那个前出现的。

#include<stdio.h>// summershell
#include<string.h>
#include<algorithm>//Manacher"马拉车"算法了解一下?
char s[20020],str[20020],news[400040];
int p[400040];//P[i]-1即以i为中心的在原文中的回文的长度
int manacher()
{
    int len=strlen(str),c=2;
    news[0]='!';news[1]='@';
    for(int i=0;i<len;++i){news[c++]=str[i];news[c++]='@';}
    news[c]='\0';//将原字符串加入特殊字符
    int id=0,mx=0,maxpos=1;//假设id是对称的字符串的中心,mx是以id为中心的对称的最大长度的右边界,右边界哦
    for(int i=1;i<c;++i)
    {
        if(i<mx){p[i]=std::min(p[2*id-i],mx-i);}//这点很重要
        else p[i]=1;//根据已知的id左边的对称情况来推右边的
        while(news[i+p[i]]==news[i-p[i]])++p[i];
            //刚刚求得最小的p[i],现在以i为中心的对称串的最大p[i]
        if(mx<i+p[i])//如果有更大的半径出现,那么就用它
        {
            id=i;
            mx=i+p[i];
        }
        if(p[maxpos]<p[i])maxpos=i;
    }
    return maxpos;
}
int main()
{
 //   freopen("in.txt","r",stdin);
    int i=0,len,cou=0,pos,anslen;
    while(scanf("%c",&s[i])!=EOF)++i;
    len=strlen(s);
    for(i=0;i<len;++i)
    {//全转成大写好判断回文
        if(s[i]>='A'&&s[i]<='Z')str[cou++]=s[i];
        else if(s[i]>='a'&&s[i]<='z')str[cou++]=s[i]-'a'+'A';
    }
    pos=manacher();
    anslen=p[pos]-1;
    printf("%d\n",anslen);//先输出最大的回文长度
    pos=pos/2-anslen/2+(news[pos]=='@');//确定回文串的起始位置
    int c=0;
    for(i=0;i<len;++i)
    {
        if((s[i]>='A'&&s[i]<='Z')||(s[i]>='a'&&s[i]<='z'))c++;
        if(c==pos)break;//已经找到字母回文在原文的起始位置,准备打印
    }
    c=0;
    while(c<anslen)//打印够anslen个长度才行
    {
        printf("%c",s[i++]);
        if((s[i-1]>='A'&&s[i-1]<='Z')||(s[i-1]>='a'&&s[i-1]<='z'))c++;
    }
    return 0;
}

如果有问题交流咨询,可以加入QQ群:673852347

80 大整数相加

作者: xxx 时间限制: 1S 章节: 字符串

问题描述 :
I have a very simple problem for you. Given two integers A and B, your job is to calculate the Sum of A + B.
输入说明 :
The first line of the input contains an integer T(1<=T<=20) which means the number of test cases. Then T lines follow, each line consists of two positive integers, A and B. Notice that the integers are very large, that means you should not process them by using 32-bit integer. You may assume the length of each integer will not exceed 1000.
输出说明 :
For each test case, you should output two lines. The first line is “Case #:”, # means the number of the test case. The second line is the an equation “A + B = Sum”, Sum means the result of A + B. Note there are some spaces int the equation. Output a blank line between two test cases.

#include<stdio.h>// summershell
#include<string.h>
int main()//怎么突然英文?意思两个大整数相加,之前不是有个类似的十六进制加法吗?一样的
{
    int T;
    char s1[2020],s2[2020],s[2020];
    scanf("%d ",&T);
    for(int t=1;t<=T;t++)
    {
        if(t!=1)printf("\n");
        scanf("%s %s",s1,s2);
        int len1=strlen(s1),len2=strlen(s2),len=0,JW=0;//JW表示进位
        int i=len1-1,j=len2-1;
        while(i>=0&&j>=0)//代码都没咋改动
        {
            int a,b,temp;
            a=s1[i]-'0';
            b=s2[j]-'0';
            temp=a+b+JW;
            JW=0;
            if(temp>9)JW=1,temp-=10;
            s[len++]=temp+'0';
            --i;
            --j;
        }
        while(i>=0)//未完成
        {
            int a,temp;
            a=s1[i]-'0';
            temp=a+JW;
            JW=0;
            if(temp>9)JW=1,temp-=10;
            s[len++]=temp+'0';
            i--;
        }
        while(j>=0)//未完成
        {
            int a,temp;
            a=s2[j]-'0';
            temp=a+JW;
            JW=0;
            if(temp>9)JW=1,temp-=10;
            s[len++]=temp+'0';
            j--;
        }
        if(JW)//如果还存在进位怎么办
        s[len++]=JW+'0';
        printf("Case %d:\n",t);
        for(i=0;i<len1;++i)printf("%c",s1[i]);
        printf(" + ");
        for(i=0;i<len2;++i)printf("%c",s2[i]);
        printf(" = ");
        for(i=len-1;i>=0;--i)printf("%c",s[i]);
        printf("\n");
    }
    return 0;
}

如果有问题交流咨询,可以加入QQ群:673852347

81 16进制加法

作者: xxx 时间限制: 1S 章节: 字符串

问题描述 :
某天、小晨在路上背着单词,突遇一外星人,外星人对小晨很感兴趣,为了考验小晨的智商,就向小晨提问简单加法,由于外星人使用16进制,所以,小晨必须用16进制回答。

输入说明 :
首先输入一个整数T,
以下T行,每行两个16进制数字
输出说明 :
T行,每行一个16进制数,为求出的两数之和。
其中的英文字母a到f为小写。

#include<stdio.h>// summershell
#include<string.h>
int main()//水题
{
    int t;
    char s1[2020],s2[2020],s[2020];
    scanf("%d ",&t);
    while(t--)
    {
        scanf("%s %s",s1,s2);
        int len1=strlen(s1),len2=strlen(s2),len=0,JW=0;//JW表示进位
        int i=len1-1,j=len2-1;
        while(i>=0&&j>=0)
        {
            int a,b,temp;
            if(s1[i]>='a')a=10+s1[i]-'a';
            else a=s1[i]-'0';
            if(s2[j]>='a')b=10+s2[j]-'a';
            else b=s2[j]-'0';
            temp=a+b+JW;
            JW=0;
            if(temp>15)JW=1,temp-=16;
            if(temp>9)s[len++]=temp-10+'a';
            else s[len++]=temp+'0';
            --i;
            --j;
        }
        while(i>=0)//未完成
        {
            int a,temp;
            if(s1[i]>='a')a=10+s1[i]-'a';
            else a=s1[i]-'0';
            temp=a+JW;
            JW=0;
            if(temp>15)JW=1,temp-=16;
            if(temp>9)s[len++]=temp-10+'a';
            else s[len++]=temp+'0';
            i--;
        }
        while(j>=0)//未完成
        {
            int a,temp;
            if(s2[j]>='a')a=10+s2[j]-'a';
            else a=s2[j]-'0';
            temp=a+JW;
            JW=0;
            if(temp>15)JW=1,temp-=16;
            if(temp>9)s[len++]=temp-10+'a';
            else s[len++]=temp+'0';
            j--;
        }
        for(i=len-1;i>=0;--i)printf("%c",s[i]);
        printf("\n");
    }
    return 0;
}

如果有问题交流咨询,可以加入QQ群:673852347

82 纯粹素数

作者: 朱凯 时间限制: 10S 章节: 字符串

问题描述 :
明明的爸爸是一位数学家,明明受他爸爸的影响从小就喜欢数学,经常向他爸爸请教数学问题。一天,明明问爸爸什么是素数,爸爸回答说:“首先,素数都是大于1的自然数;其次,素数是只能被1和其本身整除的数。例如‘3’这个数,它只能被1和3这两个整数整除,因此‘3’就是素数;但是‘4’就不是素数,因为4除了能被1和4整除外,也能被2整除,因此‘4’就不是一个素数。”
聪明的明明很快就理解了他爸爸的意思,于是又接着问他爸爸:“那么纯粹素数又是什么呢?”明明的爸爸接着回答说:“一个素数,去掉最高位,剩下的数仍为素数,再去掉剩下的数的最高位,余下的数还是素数,这样下去一直到最后剩下的个位数也还是素数,我们把这样的数称为纯粹素数。例如‘1013’这个数,它只能被1和1013整除,因此‘1013’是一个素数,我们去掉它的最高位,剩下的数是13(其实剩下的应该是013,但是前置0对一个整数来说没有意义,因此0被舍去,就剩下13),13只能被1和13整除,因此13也是个素数,我们再接着去掉它的最高位,剩下的个位数是3,3当然也是素数,因此‘1013’就是纯粹素数。更有趣的是,1013是第一个大于1000的纯粹素数,因为:
• 1000能被1、2、……、1000整除,其本身不是素数;
• 1001能被1、7、……、1001整除,其本身不是素数;
• 1002能被1、2、……、1000整除,其本身不是素数;
• 1003能被1、17、……、1003整除,其本身不是素数;
• 1004能被1、2、……、1004整除,其本身不是素数;
• 1005能被1、3、……、1005整除,其本身不是素数;
• 1006能被1、2、……、1006整除,其本身不是素数;
• 1007能被1、19、……、1007整除,其本身不是素数;
• 1008能被1、2、……、1008整除,其本身不是素数;
• 1009是一个素数,但是9能被1、3、9整除,不是素数;
• 1010能被1、2、……、1010整除,其本身不是素数;
• 1011能被1、3、……、1011整除,其本身不是素数;
• 1012能被1、2、……、1012整除,其本身不是素数;
所以从1000到1012,每个数都不是纯粹素数。”
明明对他爸爸的回答很满意,于是自己动手从1000开始寻找纯粹素数,不一会儿他就找到了20个纯粹素数,调皮的明明开始反过来考爸爸了,问他爸爸能否告诉他第2个大于1000的纯粹素数是哪个?第3个大于1000的纯粹素数是哪个?……明明的爸爸被这些突如其来的问题给难住了,他无法立刻回答出来,于是请求你帮助他回答明明的这些问题。
明明的问题可以归结为:跟据一个正整数n,求出从1,000开始从小到大的第n个纯粹素数。

输入说明 :
你写的程序需要从标准输入设备(通常为键盘)中读入多组测试数据,每组测试数据仅占一行,每行仅包括一个正整数n(1 ≤ n ≤ 20)。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。

输出说明 :
对于每一组测试数据,你写的程序需要计算出一组相应的运算结果,并将每组运算结果依次写入到标准输出设备(通常为启动该程序的文本终端,例如Windows中的命令行终端)中。每组运算结果为一个整数,即从1,000开始从小到大的第n个纯粹素数。。每组运算结果单独形成一行,其行首和行尾都没有任何空格,每组运算结果与其后一组运算结果之间没有任何空行,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行。

#include<stdio.h>// summershell
#include<string.h>//想起来49题的阴影有点不敢暴力枚举,但是看见case里的20。觉得可以试试
int prime[10001];//刚做了50题,框架就不动了
void find_prime()
{
    memset(prime,0,sizeof(prime));//0代表是素数,1代表不是
    prime[0]=prime[1]=1;
    for(int i=2;i<10001;i++)
        if(prime[i]==0)
            for(int j=i+i;j<10001;j+=i)
                prime[j]=1;
}
int weishu(int a)//计算a的位数
{
    int t=0;
    do
    {
        t++;
        a/=10;
    }while(a);
    return t;
}
int main()
{
    int N;
    find_prime();
    while(scanf("%d",&N)!=EOF)
    {
        int counter=0,num=1000;
        while(counter<N)
        {
            if(prime[num]==0)//若其为素数
            {
                int number=num,temp,i;
                while(number/10)
                {//如果不是1位数继续判定
                    for(temp=1,i=1;i<weishu(number);i++)temp*=10;
                    if(prime[number%temp]==0)number=number%temp;
                    else break;
                }//若满足条件,计数
                if(number/10==0 && prime[number]==0)counter++;
            }
            num++;
        }
        printf("%d\n",num-1);
    }
    return 0;
}

如果有问题交流咨询,可以加入QQ群:673852347

83 成绩统计

作者: 阮文灵 时间限制: 1S 章节: 结构体

问题描述 :
每次通过键盘输入5位学生如下表所示的数据,然后计算并输出每位学生的平均成绩,再输出数学成绩最高的学生的姓名及成绩。
姓名 数学成绩 政治成绩
John 88 89
Jack 90 86
Marry 76 80
Kite 55 58
Jane 56 68

输入说明 :
从键盘输入5位学生如下表所示的数据
姓名 数学成绩 政治成绩
John 88 89
Jack 90 86
Marry 76 80
Kite 55 58
Jane 56 68
输入信息包括5行,每行包括姓名、数学成绩、政治成绩。
输出说明 :
首先输出5行,每行包括学生的姓名和平均成绩,平均成绩为数学成绩加政治成绩整除2(即丢掉小数部分)。
第6行为数学成绩最高的学生的姓名及成绩。

#include<stdio.h>// summershell
struct student
{
    char s[10];
    float math,politic,avg;
}stu[10];
int main()
{
    float maxmath=-100;
    int maxstu=0;
    for(int i=0;i<5;i++)
    {
        scanf("%s %f %f",stu[i].s,&stu[i].math,&stu[i].politic);
        stu[i].avg=int((stu[i].math+stu[i].politic)/2);//说了不要小数
        if(maxmath<stu[i].math)
        {
            maxmath=stu[i].math;
            maxstu=i;
        }
    }
    for(int i=0;i<5;i++)
    {
        printf("%s %.0f\n",stu[i].s,stu[i].avg);
    }
    printf("%s %.0f %.0f\n",stu[maxstu].s,stu[maxstu].math,stu[maxstu].politic);
    return 0;
}

84 摩托车

作者: ZhouMingLIang 时间限制: 10S 章节: 结构体

问题描述 :
明明是一家摩托车厂的老板,他的厂为了迎合市场中不同消费者的需求,会生产不同型号的摩托车,这为明明的厂带来了不小的收益。有一次,一位大客户来到明明的厂洽谈生意,他需要采购一批型号各不相同的摩托车,然后他把需要的摩托车的型号告诉了明明,接着明明就需要在他所生产的摩托车中寻找到型号匹配的,如果有则卖给那个客户,如果没有则只能对客户说抱歉了。明明忙了一个上午,终于把那个客户需要的摩托车全部配齐了,然后成功的谈成了这笔生意。 事后,明明发现了一个问题,如果每个客户来,都需要这样忙一个上午,才能够知道自己生产的摩托车能否满足客户的需要,这样的工作效率实在太低了,更有可能损失很多客户,这样对工厂未来的发展也是很不利的。
于是明明找到了你,你是一名程序设计专家,明明希望你能够帮他写一个程序,程序中记录了他工厂生产的所有摩托车的数据,然后当有客户拿着摩托车的订单来洽谈生意时,只要在这个程序中输入摩托车的型号数据,程序就能够查询出工厂是否生产这类的摩托车,这样就能提高明明工厂的工作效率,有助于工厂进一步发展。
摩托车需要记录的数据有以下一些:
摩托车的型号,摩托车的颜色和摩托车马达的类型。
例如,客户需要的摩托车型号如下:

摩托车型号
a1
a2
明明拥有的摩托车类型如下:
摩托车型号 摩托车颜色 摩托车马达型号
a1                   yellow              r1
a3                     red                 r3
a4                    blue                 r4

从中可以看出,明明的工厂只有a1这个型号的摩托车。
明明的问题可以归结为:写一个程序,程序中输入客户需要的摩托车型号和明明工厂拥有的摩托车的型号。在记录明明工厂的摩托车时,还要记录摩托车的颜色和摩托车马达的类型。程序要判断明明工厂拥有的摩托车是否能满足客户的需要。
输入说明 :
你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据有多行,测试数据的第一行有两个整数n(0<n<21)、m(0<m<100),分别表示客户需要的摩托车的型号的数量和明明工厂拥有的摩托车的型号的数量。接下来的n行,表示客户所需要的摩托车型号,再接下来的m行,表示明明工厂拥有的摩托车型号,另外还包括摩托车的颜色和马达类型。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。
输出说明 :
对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将这一组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果为一行或多行数据,这些数据表示明明工厂可以满足客户需要的摩托车的型号、颜色和马达型号,这三个数据之间用一个空格隔开。如果有多行,则输出时按照摩托车型号升序排列输出。
如果明明工厂没有一种型号的摩托车可以满足客户的需要,则输出“Not found!”,不包括双引号。详细格式请参考输出样例。每组运算结果与其后一组运算结果之间没有任何空行,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行。 注:通常,显示屏为标准输出设备。

#include<stdio.h>// summershell
#include<string.h>
#include<stdlib.h>
struct motor
{
    char size1[10],color[10],mada[10];
}mot[2020];
int cmp(const void *a,const void *b)
{
    struct motor *x=(struct motor *)a,*y=(struct motor *)b;
    return strcmp((x->size1),(y->size1));
}
int main()
{
    int n,m;
    char str[2020][10],s[20][20];
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        int cou=0;
        for(int i=0;i<n;i++)
            scanf("%s",str[i]);
        for(int i=0;i<m;++i)
        {
            scanf("%s %s %s",s[1],s[2],s[3]);
            for(int j=0;j<n;++j)
                if(strcmp(s[1],str[j])==0)
                {
                    strcpy(mot[cou].size1,s[1]);
                    strcpy(mot[cou].color,s[2]);
                    strcpy(mot[cou].mada,s[3]);
                    cou++;
                    str[j][0]='\0';//抹除已经匹配好的
                    break;//不能再找了
                }
        }
        if(cou==0)printf("Not found!\n");
        else
        {
            qsort(mot,cou,sizeof(mot[0]),cmp);
            for(int i=0;i<cou;++i)printf("%s %s %s\n",mot[i].size1,mot[i].color,mot[i].mada);
        }
    }
    return 0;
}

85 扑克牌

作者: ZhouMingLiang 时间限制: 10S 章节: 结构体

问题描述 :
明明和他的三位同学在玩一种非常有趣的扑克牌游戏。
在这个游戏中,一副牌的大小怪被除去,然后把剩下的52张牌随机发给4个人,这样每个人的手中就有13张牌。
接下来的任务就是每个人把自己手中的牌按一定的顺序整理好。理牌的顺序如下:
首先按牌的大小整理,牌的大小顺序为:A,K,Q,J,T(10),9,…,2,如果牌的大小相等,则按如下的花色顺序整理:黑桃(S),红心(H),方块(D),草花(C)。
例如有一个人手中拿到的牌如下:
ST CQ S8 D8 HQ D2 H3 HK H9 H2 HT SK CK
经过整理后的牌的顺序会变为:
SK HK CK HQ CQ ST HT H9 S8 D8 H3 H2 D2
其中SK、HK、CK这三张牌的大小相同,都是K,于是根据花色的顺序整理,先是S,再是H,最后是C,所以顺序为SK、HK、CK。
当每个人把自己手中的牌整理完后,他们就开始玩非常有趣的扑克游戏了。但是玩着玩着,他们发现了一个问题:理牌的时间太长,这使得他们玩牌的兴致被大大减弱了。于是他们来求助于你,能否帮他们写一个理牌程序,帮助他们理牌,这样他们就可以不必把大量的时间花在理牌上面,而尽情享受玩牌的乐趣了。
明明的问题可以归结为:给你每人手中顺序打乱的13张牌,一共有4套,然后通过题目中描述的理牌顺序,理好这4套牌。
输入说明 :
你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,测试数据的第一行有一个整数n,表示有几副牌需要整理,接着每副牌分四行输入,每行13张牌;每张牌用两个字母表示,首字母表示花色,尾字母表示点数,两张牌之间有一个空格。每副牌与每副牌之间没有任何空行,第一副牌前面以及最后一副牌后面也都没有任何空行。 注:通常,键盘为标准输入设备。
输出说明 :
对于每一副牌,你写的程序要求计算出一组相应的运算结果,并将每组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。对于每组输入的牌,输出排序后的牌,分四行输出,输出样式与输入相同。每组运算结果与其后一组运算结果之间有一个空行,第一组运算结果前面及最后一组运算结果后面没有空行。 注:通常,显示屏为标准输出设备。

#include<stdio.h>// summershell
#include<string.h>
#include<stdlib.h>//考排序的,emm,他的大小规则不能直接比较,所以用结构体把定义的大小写进去
struct node
{
    char str[20];
    int x,y;
}poker[20];
int cmp(const void *a,const void *b)
{
    struct node *m=(struct node *)a,*n=(struct node *)b;
    if((m->x)!=(n->x))return (m->x)-(n->x);
    else return (m->y)-(n->y);
}
int convert(char c)
{//A,K,Q,J,T(10),9,…,2
    if(c=='A')return 1;
    if(c=='K')return 2;
    if(c=='Q')return 3;
    if(c=='J')return 4;
    if(c=='T')return 5;
    if(c=='9')return 6;
    if(c=='8')return 7;
    if(c=='7')return 8;
    if(c=='6')return 9;
    if(c=='5')return 10;
    if(c=='4')return 11;
    if(c=='3')return 12;
    if(c=='2')return 13;
    if(c=='S')return 1;
    if(c=='H')return 2;
    if(c=='D')return 3;
    if(c=='C')return 4;
}
int main()
{
    int T,c=1;
    scanf("%d",&T);
    while(T--)
    {
        if(c++!=1)printf("\n");
        for(int i=0;i<4;++i)
        {
            for(int j=0;j<13;++j)
            {
                scanf("%s",poker[j].str);
                poker[j].y=convert(poker[j].str[0]);
                poker[j].x=convert(poker[j].str[1]);
            }
            qsort(poker,13,sizeof(poker[0]),cmp);
            for(int j=0;j<13;++j)printf(j==0?"%s":" %s",poker[j].str);
            printf("\n");
        }

    }
    return 0;
}

如果有问题交流咨询,可以加入QQ群:673852347

86 商店购物

作者: xxx 时间限制: 1S 章节: 结构体

问题描述 :
在商店中,每一种商品都有一个价格(用整数表示)。例如,一朵花的价格是 2 zorkmids (z),而一个花瓶的价格是 5z 。为了吸引更多的顾客,商店举行了促销活动。
促销活动把一个或多个商品组合起来降价销售,例如: 三朵花的价格是 5z 而不是 6z, 两个花瓶和一朵花的价格是 10z 而不是 12z。
编写一个程序,计算顾客购买一定商品的花费,尽量利用优惠使花费最少。
尽管有时候添加其他商品可以获得更少的花费,但是你不能这么做。
对于上面的商品信息,购买三朵花和两个花瓶的最少花费是:以优惠价购买两个花瓶和一朵花(10z),以原价购买两朵花(4z)
输入说明 :
输入包括一些商店提供的优惠信息,接着是购物清单。
第一行 优惠商品的种类数(0 <= s <= 99)。
第二行…第s+1 行 每一行都用几个整数来表示一种优惠方式。
第一个整数 n (1 <= n <= 5),表示这种优惠方式由 n 种商品组成。后面 n 对整数 c 和 k 表示 k (1 <= k <= 5)个编号为 c (1 <= c <= 999)的商品共同构成这种优惠,最后的整数 p 表示这种优惠的优惠价(1 <= p <= 9999)。优惠价总是比原价低。
第 s+2 行 这一行有一个整数 b (0 <= b <= 5),表示需要购买 b 种不同的商品。
第 s+3 行…第 s+b+2 行 这 b 行中的每一行包括三个整数:c ,k ,和 p 。c 表示唯一的商品编号(1 <= c <= 999),k 表示需要购买的 c 商品的数量(1 <= k <= 5)。p 表示 c 商品的原价(1<= p <= 999)。
最多购买 5*5=25 个商品。
输出说明 :
只有一行,输出一个整数:购买这些物品的最低价格。

#include<stdio.h>// summershell
#include<string.h>//动态规划的题,状态方程是dp[x1,x2,x3,x4,x5]=min(dp[x1,x2,x3,x4,x5],dp[x1-c1i,x2-c2i,x3-c2i,x4-c3i,x5-c5i]+w[i])就是最优解建立在不使用和使用第i种优惠方案的比较上得到的
#include<algorithm>//所以这种一定是最优的,因为dp一直在变动的,当发现有更优惠的方案时候就记录下来。使用不同的搭配方案得到的最优的结果
struct discount
{
    int n,ID[2020],price;//表示编号为i的商品需要几个来进行优惠
}Dis[2020];//优惠方式
struct goods
{
    int id,quan,price;//商品的信息
}GOOD[2020];
int main()
{
    int dp[6][6][6][6][6];//表示购买x1个第一种,x2个第二种,x3个第三种,x4个第四种,x5个第五种的总费用,下标6,商品的购买数量足够了。
    int s,b,temp;
    scanf("%d",&s);
    memset(Dis,0,sizeof(Dis));
    memset(GOOD,0,sizeof(GOOD));
    for(int i=0;i<s;++i)
    {
        scanf("%d",&Dis[i].n);
        for(int j=0;j<Dis[i].n;++j)
        {
            scanf("%d",&temp);
            scanf("%d",&Dis[i].ID[temp]);
        //    printf("%d-%d-%d\n",Dis[i].ID[3],Dis[i].ID[1],Dis[i].ID[temp]);
        }
        scanf("%d",&Dis[i].price);
    }
    scanf("%d",&b);//购买的种类
    for(int i=0;i<b;++i)
    {
        scanf("%d %d %d",&GOOD[i].id,&GOOD[i].quan,&GOOD[i].price);
    }
    //需要赋初值,即是最初的没有任何优惠情况下的价格,5重循环
    for(int i=0;i<=GOOD[0].quan;++i)//有可能少于5种,没事还可以按照5重循环来
        for(int j=0;j<=GOOD[1].quan;++j)
        for(int k=0;k<=GOOD[2].quan;++k)
        for(int l=0;l<=GOOD[3].quan;++l)
        for(int m=0;m<=GOOD[4].quan;++m)
        dp[i][j][k][l][m]=GOOD[0].price*i+GOOD[1].price*j+GOOD[2].price*k+GOOD[3].price*l+GOOD[4].price*m;

    //准备工作已经做好,开始进行动态规划,每种组合方案和优惠方案的搭配
    for(int d=0;d<s;++d)
    {//把不使用,使用一次,二次。。多次的情况都考虑进去,保存到dp里
        int d0=Dis[d].ID[GOOD[0].id];
        int d1=Dis[d].ID[GOOD[1].id];
        int d2=Dis[d].ID[GOOD[2].id];
        int d3=Dis[d].ID[GOOD[3].id];
        int d4=Dis[d].ID[GOOD[4].id];
//由于每种优惠方案都有起始数量,我们就从起始数量开始
        for(int i=d0;i<=GOOD[0].quan;++i)
        for(int j=d1;j<=GOOD[1].quan;++j)
        for(int k=d2;k<=GOOD[2].quan;++k)
        for(int l=d3;l<=GOOD[3].quan;++l)
        for(int m=d4;m<=GOOD[4].quan;++m)
        dp[i][j][k][l][m]=std::min(dp[i][j][k][l][m],dp[i-d0][j-d1][k-d2][l-d3][m-d4]+Dis[d].price);
    }
    printf("%d\n",dp[GOOD[0].quan][GOOD[1].quan][GOOD[2].quan][GOOD[3].quan][GOOD[4].quan]);
    return 0;
}

如果有问题交流咨询,可以加入QQ群:673852347

87 挤牛奶

作者: xxx 时间限制: 1S 章节: 结构体

问题描述 :
三个农民每天清晨5点起床,然后去牛棚给3头牛挤奶。第一个农民在300时刻(从5点开始计时,秒为单位)给他的牛挤奶,一直到1000时刻。第二个农民在700时刻开始,在 1200时刻结束。第三个农民在1500时刻开始2100时刻结束。期间最长的至少有一个农民在挤奶的连续时间为900秒(从300时刻到1200时刻),而最长的无人挤奶的连续时间(从挤奶开始一直到挤奶结束)为300秒(从1200时刻到1500时刻)。 你的任务是编一个程序,读入一个有N个农民(1 <= N <= 5000)挤N头牛的工作时间列表,计算以下两点(均以秒为单位): 最长至少有一人在挤奶的时间段。 最长的无人挤奶的时间段。
输入说明 :
Line 1: 一个整数N。 Lines 2…N+1: 每行两个小于1000000的非负整数,表示一个农民的开始时刻与结束时刻。
输出说明 :
一行,两个整数,即题目所要求的两个答案,以一个空格分隔。

#include<stdio.h>// summershell
#include<stdlib.h>//考虑到N<5000的情况,不如全排序后,挨个检查
int cmp(const void *a,const void *b)
{
    return (((int *)a)[0])-(((int *)b)[0]);
}
int main()
{
    int T,a[5010][2],cou=0;
    scanf("%d",&T);
    for(int i=0;i<T;++i)scanf("%d %d",&a[i][0],&a[i][1]);
    qsort(a,T,sizeof(a[0]),cmp);
    a[T][0]=999999999;
    for(int i=0;i<T+1;++i)
    {
        if(a[i][1]>=a[i+1][0])a[i+1][0]=a[i][0];//把时间段压缩到一个时间段里
        else//否则就记录下这段
        {
            a[cou][0]=a[i][0];
            a[cou][1]=a[i][1];
            cou++;
        }
    }
    int maxlen=a[0][1]-a[0][0],minlen=0;
    for(int i=0;i<cou;++i)
    {
        if(maxlen<a[i][0]-a[i][1])maxlen=a[i][0]-a[i][1];//记录最大值
        if(i>0)//求最不挤奶时间
        {
            if(a[i][0]-a[i-1][1]>minlen)minlen=a[i][0]-a[i-1][1];
        }
    }
    printf("%d %d\n",maxlen,minlen);
    return 0;
}

如果有问题交流咨询,可以加入QQ群:673852347

88 顺序的分数

作者: xxx 时间限制: 1S 章节: 结构体

问题描述 :
输入一个自然数N,请写一个程序来增序输出分母小于等于N的既约真分数(即无法再进行约分的小于1的分数)
输入说明 :
单独的一行,一个自然数N(1…20)
输出说明 :
每个分数单独占一行
按照分数大小升序排列
对于分子为0的分数,仅输出0/1,不输出其它分母的分数,比如0/2, 0/3。

#include<stdio.h>// summershell
#include<algorithm>
using namespace std;
struct number
{
    int a,b;//a分子,b分母
}num[2000];
int cmp(struct number a,struct number b)
{
    return a.a*b.b<b.a*a.b;
}
int judge(int a,int b)//6/8怎么办?递归调用
{
    if(a==0)return b;       //若能约分,则最后摸到的数一定不是1
    else return judge(b%a,a);
}
int main()
{
    int N,count=-1;
    num[++count].a=0;
    num[count].b=1;
    scanf("%d",&N);
    for(int i=2;i<=N;i++)
    {
        for(int j=1;j<=i-1;j++)//限制分子小于分母i
        {
            if(judge(j,i)==1)
            {
                num[++count].a=j;
                num[count].b=i;
            }
        }
    }
    sort(num,num+count,cmp);
    for(int i=0;i<=count;i++)printf("%d/%d\n",num[i].a,num[i].b);
    return 0;
}

89 分糖果

作者: xxx 时间限制: 10S 章节: 一维数组

问题描述 :
肖恩和帕特里克是兄弟,他们从他们的父母那里得到了很多糖果。每一块糖具有一个正整数的价值,孩子们希望分他们得到的糖果。首先,肖恩将这些糖果分成两堆,并选择一堆给帕特里克。然后,帕特里克将尝试计算每堆的价值,其中每堆的价值是那堆糖果价值的总和,如果他觉得没有平等的价值,他将开始哭了起来。
不幸的是,帕特里克太小了,所以不能正确的计算。他只会二进制无进位的加法。比如说,他想算12(二进制为1100)加5(二进制为101),他会把最右边的两位加法算正确,但是第三位会忘记进位。(即0+0=0,0+1=1,1+0=1,1+1=0)
因此,帕特里克算12加5的结果为9。下面几个是帕特里克算的结果:
5 + 4 = 1
7 + 9 = 14
50 + 10 = 56
肖恩数学很好,他想得到价值总和更高的糖果并且不让他的弟弟哭。如果可能,他会分成两个非空的糖果袋,让帕特里克认为,双方都有相同的值的糖果。给你每一袋糖果每一块糖果的价值,我们想知道是否可能让帕特里克相信他们得到糖果价值的总量是相同的。如果可能计算出肖恩能得到的最大的价值。
输入说明 :
第一行输入T(1<T<10),表示接下来输入T组测试数据。
每组测试数据占一行,每行包含以下数据,N C1 C2 … Cn(其中N(2 ≤ N ≤ 10)代表从父母那里得到糖果的总数,C(1 ≤ Ci ≤ 100)代表每块糖果的价值)

输出说明 :
若不能输出NO,若能则输出肖恩得到的最大的价值。

#include<stdio.h>// summershell
//这不是坑弟弟吗?哈哈哈。弟弟的算法是不进位加法,即是异或的操作,异或的一个特点是两个数相同异或结果是0。
//注意题上的条件,弟弟会计算每一堆的糖果(两个人的),然后进行比较。想想弟弟怎么加的,异或,把自己的那一堆异或完。再去异或哥哥的。若两堆数量一致,或者按照弟弟的加法得到"一样的数",那么我们对这两个结果异或会得到0。否则就是1,不能平分输出NO。可知对所有的数都进行异或操作,得到0可以分,否则不能分。因为异或的结果是0。那么哥哥为了利益最大化完全可以,只对弟弟一个糖果,且是最小值,其他的糖果异或后就是等于这个最小值。
int main()
{
    int T,N;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&N);
        int sum=0,minlen=1000,temp,flag=0;
        for(int i=0;i<N;++i)
        {
            scanf("%d",&temp);
            sum+=temp;//找到总和
            if(minlen>temp)minlen=temp;//找到弟弟的最小值
            flag=flag^temp;
        }
        printf(flag==0?"%d\n":"NO\n",sum-minlen);
    }
    return 0;
}

如果有问题交流咨询,可以加入QQ群:673852347

90 循环数

作者: xxx 时间限制: 1S 章节: 一维数组

问题描述 :
循环数是那些不包括0这个数字的没有重复数字的整数 (比如说, 81362) 并且同时具有一个有趣的性质, 就像这个例子:
如果你从最左边的数字( 记为n,在这个例子中是8) 开始往右边数,一直数n个数字(如果已经到了最右边则回到最左边),你会停在另一个不同的数字上。如果停在一个相同的数字上,这个数就不是循环数。
就像: 8 1 3 6 2 从最左边接下去数8个数字: 1 3 6 2 8 1 3 6 所以下一个数字是6. 重复这样做 (这次从’6’开始数6个数字) 并且你会停止在一个新的数字上: 2 8 1 3 6 2, 也就是2. 再这样做 (这次数两个): 8 1。 再一次 (这次数一个): 3。 又一次: 6 2 8, 这时你回到了起点。
此时,我们数到的数字依次是:8 6 2 1 3,即每一个数字都被数了1次,并且回到了起点。
如果你将每一个数字都数了1次以后没有回到起点, 你的数字不是一个循环数。
给你一个数字 M (在1到9位之间), 找出第一个比 M大的循环数(输入的M保证这个循环数能保存在4位的有符号整数中)。
输入说明 :
仅仅一行, 包括M
输出说明 :
仅仅一行,包括第一个比M大的循环数。

#include<stdio.h>// summershell
#include<string.h>
int visit[10],num[10];//标记是否访问过
int diff(int a)     //判断是否都是不同的数字
{
    memset(visit,0,sizeof(visit));
    while(a)
    {
        if((a%10==0) || visit[a%10])return 0;
        visit[a%10]=1;
        a/=10;
    }
    return 1;
}
int judge(int a)//判断是否是循环数
{
    int counter=0,stack[10],top=-1;//counter位数
    while(a)
    {
        stack[++top]=a%10;
        a/=10;
    }
    while(top!=-1)//利用栈正确的放置这个数
        num[counter++]=stack[top--];
    memset(visit,0,sizeof(visit));
    int i=0,j=0;
    while(i<counter)//判定成功才可以返回1
    {
        j=(j+num[j])%counter;
        if(visit[num[j]]==0)i++;
        else return 0;
        visit[num[j]]=1;
    }//这个while的细节好多,一定要注意。
    return 1;
}
int main()
{
    int M;
    scanf("%d",&M);
    while(1)
        if(diff(++M) && judge(M))break;
    printf("%d\n",M);

    return 0;
}

如果有问题交流咨询,可以加入QQ群:673852347

91 棋盘游戏

作者: xxx 时间限制: 1S 章节: 宽度优先搜索

问题描述 :
大小为3的棋盘游戏里有3个白色棋子,3个黑色棋子,和一个有7个格子一线排开的木盒子。3个白棋子被放在一头,3个黑棋子被放在另一头,中间的格子空着。
初始状态: WWW_BBB
目标状态: BBB_WWW
在这个游戏里有两种移动方法是允许的:

  1. 你可以把一个棋子移到与它相邻的空格;
  2. 你可以把一个棋子跳过一个(仅一个)与它不同色的棋子到达空格。

大小为N的棋盘游戏包括N个白棋子,N个黑棋子,还有有2N+1个格子的木盒子。
这里是3-棋盘游戏的解,包括初始状态,中间状态和目标状态:

WWW BBB
WW WBBB
WWBW BB
WWBWB B
WWB BWB
W BWBWB
WBWBWB
BW WBWB
BWBW WB
BWBWBW
BWBWB W
BWB BWW
B BWBWW
BB WBWW
BBBW WW
BBB WWW

请编一个程序解大小为N的棋盘游戏(1 <= N <= 12)。要求用最少的移动步数实现。

输入说明 :
一个整数N。
输出说明 :
用空格在棋盘的位置(位置从左到右依次为1, 2, …, 2N+1)表示棋盘的状态。输出棋盘的状态变换序列,每行20个数(除了最后一行)。 输出的解还应当有最小的字典顺序(即如果有多组移动步数最小的解,输出第一个数最小的解;如果还有多组,输出第二个数最小的解;…)。

#include<stdio.h>// summershell
//看了看N==9的数据发现了规律。按照规律直接写吧,快竣工了。
//规律1.先看空格左2位是否为W,可不可以过来,不可以的话,看右2位的是不是B可不可以过来
//规律2.在1都不行时候,若在中心线右边,若为W_B则移动B。若在中心线左边若为W_B,则W过去。若两边一样,则最简单了
int finish(int a[],int N)//判定是否完成
{
    for(int i=1;i<=N;i++)if(a[i]!=2)return 0;
    return 1;
}
int main()//Wy用1表示,B用2表示
{
    int a[2020],N,cou=1,i;
    scanf("%d",&N);
    for(i=1;i<=N;i++)a[i]=1;//先初始化好
    for(i=N+2;i<=2*N+1;++i)a[i]=2;
    i=N+1;//表示空格所在的位置
    while(!finish(a,N))
    {
        if(a[i-2]==1&&a[i-1]==2)//第一规律
            {a[i]=1;a[i-2]=0;i=i-2;}//交换
        else if(a[i+2]==2&&a[i+1]==1)//第二规律
            {a[i]=2;a[i+2]=0;i=i+2;}//交换
        else if(a[i+1]==a[i-1])
        {
            if(a[i-1]==1){a[i]=1;a[i-1]=0;i=i-1;}
            else if(a[i-1]==2){a[i]=2;a[i+1]=0;i=i+1;}
        }
        else if(i<=N+1&&a[i-1]==1&&a[i+1]==2)
            {a[i]=1;a[i-1]=0;i=i-1;}
        else if(i>N+1&&a[i-1]==1&&a[i+1]==2)
            {a[i]=2;a[i+1]=0;i=i+1;}
        else if(i==2*N+1)//边界规律,emm测case时发现的,边界忘了考虑
            {a[i]=a[i-1];a[i-1]=0;i=i-1;}
        else if(i==1)
            {a[i]=a[i+1];a[i+1]=0;i=i+1;}

        printf(cou%20==1?"%d":" %d",i);
        if(cou++%20==0)printf("\n");
    }
    printf(cou%20==1?"%d":" %d",N+1);
    if(cou++%20==0)printf("\n");
    return 0;
}

如果有问题交流咨询,可以加入QQ群:673852347

92 表达式求值

作者: 朱星垠 时间限制: 1S 章节: 字符串

问题描述 :
以字符串形式输入仅有整数和加减(正负)号构成的表达式,输出该表达式的值。
输入说明 :
标准输入设备中有多组测试数据,每组输入数据由一行组成,输入仅有整数和加减(正负)号构成的表达式(但是表达式可以插入空格)。
输出说明 :
依次输出从标准输入设备中读入的每一组测试数据对应的结果,输出一行,输出该表达式的值。所有数据前后没有多余的空格,两组数据之间也没有多余的空行。

#include<stdio.h>// summershell
#include<string.h>
int main()
{
    char s[1000];
    s[0]='+';//不失去一般性
    while(gets(s+1)!=NULL)
    {
        int sum=0,flag=1,temp=0;//sum总和,flag正负,temp可能不止一位数啊
        for(int i=0;i<strlen(s);++i)
        {
            if(s[i]=='+' || s[i]=='-')
            {
                sum+=flag*temp;
                temp=0;
                flag=s[i]=='-'?-1:1;
            }
            else if(s[i]>='0' && s[i]<='9')
            {
                temp=temp*10+s[i]-'0';
                continue;
            }
        }
        printf("%d\n",sum+=flag*temp);
    }
    return 0;
}

93 隐藏口令

作者: 5.5.2 时间限制: 1S 章节: 字符串

问题描述 :
有时候程序员有很奇怪的方法来隐藏他们的口令。
Billy"Hacker"Geits会选择一个字符串S(由L个小写字母组成,5<=L<=100,000),然后他把S顺时针绕成一个圈。
如字符串cbadfa,绕成一个圈后,我们认为字符串首尾相连。
每次取其中一个字母作为起始字母,并顺时针依次取字母而组成一个字符串。这样将得到一些字符串。
比如字符串cbadfa,按照以上规则取出的字符串有:
cbadfa badfac adfacb dfacba facbad acbadf
我们找到最小的那个字符串,可知为acbadf,也可知道它的第一个字符’a’在原字符串cbadfa中为第6个字符(位置从1开始),
将得到的结果6减1得到5,这就是我们需要的口令。

再比如字符串alabala,绕成一个圈后,每次取其中一个字母作为起始字母,并顺时针依次取字母而组成一个字符串。这样将得到一些字符串:
alabala labalaa abalaal balaala alaalab laalaba aalabal
我们找到最小的那个字符串,可知为aalabal,它的第一个字母’a’在原字符串中位置为7,7-1=6,则6为口令。

注:如果按照规则有两个字符串都是最小的,则取前面那一个。
输入说明 :
第一行:一个数L
第二行及之后:字符串S。
注意:字符串S可跨多行,但其中的’\n’不算成S中的字符
输出说明 :
一行,为得到的口令。
无多余空格或空行。

 
#include<stdio.h>// summershell
//最直接的方法是分出个串,然后排序,但是10万的数据,着实不好办,不如就在圈里面循环判定
int main()
{
    char a[100000],c;
    int minum=0,L,i=0;
    scanf("%d ",&L);
    while(scanf("%c",&c)!=EOF && i<L)
        if(c>='a' && c<='z')a[i++]=c;
    for(i=0;i<L;i++)
    {
        if(minum!=i)
        {
            int p=minum,q=i,j=0;
            while(a[p]==a[q]&&j<L)//循环判定&&防止死循环
            {
                p=(p+1)%L;
                q=(q+1)%L;
                j++;//
            }
            if(a[p]>a[q])minum=i;
        }
    }
    printf("%d\n",minum);
    return 0;
}

94 分数化小数

作者: xxx 时间限制: 1S 章节: 字符串

问题描述 :
写一个程序,输入一个形如N/D的分数(N是分子,D是分母),输出它的小数形式。
如果小数有循环节的话,把循环节放在一对圆括号中。
例如, 1/3 = .33333333 写成0.(3)
41/333 = 0.123123123… 写成0.(123)
用xxx.0 表示整数
典型的转化例子: 1/3 = 0.(3)
22/5 = 4.4
1/7 = 0.(142857)
2/2 = 1.0
3/8 = 0.375
45/56 = 0.803(571428)
输入说明 :
单独的一行包括被空格分开的 N和D, 1 <= N,D <= 100000。
输出说明 :
小数的表示方法上面说的很明白了,如果输出的长度超过76个字符,每行输出76个字符(包括小数点、括号等)。

#include<stdio.h>// summershell
#include<string.h>//一个分数可以是整数或者有限小数,无限循环小数。所以最难搞的是循环节了
//关于循环节,手除笔算研究后发现,若X除以Y余下A,之后再除若还得到了A就代表已经开始循环了,例如例子的41/333,(乘10是为了直接得到商和余数)410%333=77,770%333=104,1040%333=41(看吧,一个循环)。基本思想已有,Let's do it!
int main()
{
  //  freopen("in.txt","r",stdin);
    int D,N;
    int Xiao[10255],st,en,Yu,cou,visit[100001];//visit用来监视是否有循环节出现
    while(scanf("%d %d",&N,&D)!=EOF)
    {
        printf("%d.",N/D);//整数部分很Easy啦
        //控制输出最多输出76个字符
        int tt=N/D,control=2;//考虑0.的情况出现
        while(tt/10) {tt/=10;control++;}

        if(N%D==0)printf("0\n");//整数的情况
        else
        {//小数部分
            memset(visit,-1,sizeof(visit));
            memset(Xiao,0,sizeof(Xiao));
            Yu=N%D;//从这开始存进去余数了
            cou=0;
            Xiao[cou++]=(Yu*10)/D;//把商保存输出
            visit[Yu]=cou-1;//把余数出现的位置保存,方便输出循环节
            Yu=(Yu*10)%D;//余数*10模D得到新的余数
            int flag=1;
            while(Yu && flag)
            {
                Xiao[cou++]=Yu*10/D;
                if(visit[Yu]==-1)visit[Yu]=cou-1;
                else {flag=0;st=visit[Yu];en=cou-1;}//余数若重复即为循环节
                Yu=(Yu*10)%D;
            }
            if(flag==0)//有循环节时候
            {
                for(int i=0;i<=en;++i)
                {
                    if(i==st){printf("(");control++;if(control>=76)control=0,printf("\n");}
                    else if(i==en){printf(")");break;}
                    printf("%d",Xiao[i]);
                    control++;
                    if(control>=76)control=0,printf("\n");
                }
            }
            else for(int i=0;i<cou;++i){printf("%d",Xiao[i]);control++;if(control>=76)control=0,printf("\n");}
            if(control!=0)printf("\n");
        }
    }
    return 0;
}/*提交了5次,2365那个case始终没过,难道是我开的Xiao数组太短了?因为看了下N和D的范围100000那么长,有可能2020长度不满足啊(虽然因为2020考研设置的大小不如把东华的院校代码写上吧,哈哈哈),试试吧!提交了,果然是,但是这次PE了,修改下格式就OK了*/

如果有问题交流咨询,可以加入QQ群:673852347

95 回文或镜面回文

作者: Turbo 时间限制: 1S 章节: 字符串

问题描述 :
给出字符串,判断其是否是回文或镜面回文。
给定一个由数字或字母组成的字符串,如果该字符串正读、反读都一样,则该字符串被称作回文字符串。例如,"ABCDEDCBA"就是回文字符串。
给定一个由数字或字母组成的字符串,将字符串中每个字符转换为对应的镜面字符(有镜面字符)或保持不变(无对应镜面字符),如果转换后的字符串反读的结果与字符串转换前正读的结果相同,则该字符串被称作镜面字符串。例如,"3AIAE"就是镜面字符串。
如果一个字符串既是回文字符串又是镜面字符串,则称该字符串为镜面回文字符串。例如,"ATOYOTA"就是镜面回文字符串。

所有有效字符与其镜面字符见下表:
字符 镜面字符 字符 镜面字符 字符 镜面字符

A	A	M	M	Y	Y
B		N		Z	5
C		O	O	1	1
D		P		2	S
E	3	Q		3	E
F		R		4	
G		S	2	5	Z
H	H	T	T	6	
I	I	U	U	7	
J	L	V	V	8	8
K		W	W	9	
L	J	X	X		

注意:数字0与字母O视作同一字符,都用字母O表示。

输入说明 :
输入包含多个字符串,每行一个字符串,每个字符串包含1—20个有效字符,保证每个字符串中不会出现非法字符。

输出说明 :

 
#include<stdio.h>// summershell
#include<string.h>//来到了最后一题,有点激动和不舍鸭!
char convert(char c)//镜面转换
{
    if(c=='E')return '3';
    if(c=='3')return 'E';
    if(c=='J')return 'L';
    if(c=='L')return 'J';
    if(c=='0')return 'O';
    if(c=='S')return '2';
    if(c=='2')return 'S';
    if(c=='Z')return '5';
    if(c=='5')return 'Z';
    return c;//否则就不变
}
int huiwen(char s[])//老生常谈的回文判别
{
    int len=strlen(s);
    for(int i=0;i<=(len-1)/2;++i)if(s[i]!=s[len-1-i])return 0;
    return 1;
}
int JudgeJingMian(char s[])//判断是否是镜面的
{
    char st[2020];
    int len=strlen(s);
    for(int i=0;i<len;++i)st[i]=convert(s[i]);//转换完成
    for(int i=0;i<len;++i)if(s[i]!=st[len-i-1])return 0;//判定
    return 1;
}
void judge(char s[])
{
    if(huiwen(s)==0 && JudgeJingMian(s)==0)
        puts(" -- is not a palindrome.");
    else if(huiwen(s)==1 && JudgeJingMian(s)==0)puts(" -- is a regular palindrome.");
    else if(huiwen(s)==0 && JudgeJingMian(s)==1)puts(" -- is a mirrored string.");
    else if(huiwen(s)==1 && JudgeJingMian(s)==1)puts(" -- is a mirrored palindrome.");
}
int main()
{
    char str[2020];
    while(gets(str)!=NULL)
    {
        printf("%s",str);
        judge(str);
        putchar('\n');
    }
    return 0;
}
/*最后一题略简单了,哈哈,进阶篇刷完了,希望一次AC。我还希望我能成为东华大学2020年计算机科学与技术的研究生!*/

如果有问题交流咨询,可以加入QQ群:673852347

  • 4
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值