2019“西邮杯”初赛题解

1、加法变乘法
题目描述:

 已知X可以写成从1开始连续若干个整数的和, 现在要求把其中两个不相邻的加号变乘号,使得结果为Y。找出所有满足条件的可能答案并输出(把两个乘号左边的数字用小括号括起来,中间用英文逗号间隔,两个括号之间不空格);若找不到满足的条件,则输出“NONE”字样。编写程序,完成n组数据的判定。

例如:当X为1225,Y为2015时
因为:1+2+3+ ... + 49 = 1225
   1+2+3+...+1011+12+...+2728+29+...+49 = 2015
所以:一个解为(10,27)。

输入

第一行为n值,接下来依次n行的第一个数据是加法结果X,第二个数据是变乘法后的结果Y,以空格间隔。

输出

输出n行,每一行的格式为“(,)(,)”(或者“NONE”)。请严格按照格式书写,不能出现其它文字或符号。

样例输入

3
1225 2015
1224 2015
1275 2065

样例输出

(10,27)(16,24)
NONE
(10,27)(16,24)

题解:观察题目,用X和Y减去变化的量,最后结果相同即满足条件。

源代码:

#include
#include
int main()
{
    int i,j;
    int x,y,n,flag;
    scanf("%d",&n);
    while(n--)
    {
        flag=1;
        scanf("%d %d",&x,&y);
        for(i=1;i

2、互满数

题目描述

编写求因子和函数,该函数返回形参n的因子之和。要求调用该因子和函数,求出x范围内(包含x)所有的互满数。所谓互满数是指:如果有两个数,每一个数的所有因子之和恰好等于对方,则称这两个数为“互满数”。

输入

从键盘输入一个正整数x。

输出

从小到大依次输出互满数,每对互满数用小括号括起来(小数在前,大数在后),中间用英文逗号间隔,两个括号之间不空格。

样例输入

10000

样例输出

(220,284)(1184,1210)(2620,2924)(5020,5564)(6232,6368)

本题刚开始我的思路是:用函数写。先写一个函数专门用来计算每个数的因子和,再在主函数里面利用循环和、引入函数、判断条件的方式来找出一定范围内的互满数。

源代码:

#include
int SUM(int n)
{
    int i,sum=0;
    for(i=1;i<=n/2;i++)
    {
        if(n%i==0)
        {
            sum=sum+i;
        }
    }
    return sum;
}
int main()
{
    int x;
    scanf("%d",&x);
    int i,j;
    int t1,t2;
    for(i=2;i

但是这样的代码由于循环嵌套的过多,导致过大的数字运行速度非常慢,会超时,所以这样的方法是无法提交正确的。

后来咨询了大佬,大佬给了一个相对我的而言比较优化的代码:

#include
int main()
{
    int x;
    scanf("%d",&x);
    int i,j,k;
    int sum1=0,sum2=0;
    for(i=2;i<=x;i++)
    {
        sum1=0,sum2=0;
        for(j=1;j<=i/2;j++)
        {
            if(i%j==0)
            {
                sum1=sum1+j;
            }
        }
        if(i>=sum1)
            continue;   //减少重复
        for(k=1;k<=sum1/2;k++)
        {
            if(sum1%k==0)
            {
                sum2=sum2+k;
            }
        }
        if(sum2==i)
        {
            printf("(%d,%d)",sum1sum2? sum1:sum2);    //双目运算:第二个逗号之前 比较sum1和sum2的大小,如果sum1比sum2小,则输出sum1。 第二个逗号之后  比较sum1和sum2的大小,如果sum1比sum2大,则输出sum1。
        }
    }
 } 
3、按价格排序并输出
题目描述

一本图书的信息有: 编号、书名、作者、出版社、出版日期、价格。设计一个结构体类型描述图书信息,并实现输入多本(不超过20本)图书信息,存储在该结构体的数组变量中,按价格从低到高排序并输出图书信息。

输入

第一行输入图书的本数,以后每行输入一本图书的信息;每本图书信息的输入说明如下:输入时,各个信息之间空格间隔;编号为整数;书名、作者、出版社均为长度不超过20的字符串;出版日期的输入格式为yyyy-mm-dd,例如(2017-5-2);价格为实数。

输出

以列表方式输出:(注意,输出中除了汉字外,其他符号均为英文符号
第一行输出标题行,分别输出:“编号”、“书名”、“作者”、“出版社”、“出版日期”、“价格”;相邻两项之间以一个空格间隔。(参见样例)
以后每行输出一本书,依次输出<编号>,<书名>,<作者>,<出版社>,<出版日期>,<价格(小数点后保留2位)>,相邻两项之间以一个空格间隔。(参见样例)

样例输入

4
2 数据结构 耿国华 高等教育出版社 2005-7-1 28.00
4 大学英语 LEE 清华出版社 1990-4-1 34.6
6 草莓点心 噼里啪啦 二十一世纪出版社 2008-8-8 18.00
7 车来了 噼里啪啦 二十一世纪出版社 2008-9-9 18.50

样例输出

编号 书名 作者 出版社 出版日期 价格
6 草莓点心 噼里啪啦 二十一世纪出版社 2008年8月8日 18.00
7 车来了 噼里啪啦 二十一世纪出版社 2008年9月9日 18.50
2 数据结构 耿国华 高等教育出版社 2005年7月1日 28.00
4 大学英语 LEE 清华出版社 1990年4月1日 34.60

本题就是简单的结构体的运用,冒泡排序的运用

代码源:

#include
struct Book
{
    int num;
    char name[20];
    char editor[20];
    char pub[40];
    int year;
    int moth;
    int day;
    float price;
};
int main()
{
    int n;
    scanf("%d",&n);
    struct Book book[n];
    struct Book t;
    int i,j;
    for(i=0;ibook[j+1].price)
            {
                t=book[j];
                book[j]=book[j+1];
                book[j+1]=t;
            }
        }
    }
    printf("编号 书名 作者 出版社 出版日期 价格\n");
    for(i=0;i
4、乘积最大
题目描述

设有一个长度为N的数字串,要求选手使用K个乘号将它分成K+1个部分,找出一种分法,使得这K+1个部分的乘积能够为最大。
同时,为了帮助选手能够正确理解题意,主持人还举了如下的一个例子:
有一个数字串:312, 当N=3,K=1时会有以下两种分法:
1、3 x12=36
2、31 x 2=62
这时,符合题目要求的结果是:31*2=62。
现在,请你帮助你的好朋友设计一个程序,求得正确的答案。

输入

输入共有两行:
第一行共有2个自然数N,K(4≤N≤10,1≤K≤5)。
第二行是一个长度为N的数字串。

输出

一个整数,表示所求得的最大乘积。

样例输入

4 2
1231

样例输出

62

本题要运用动态规划
暂时没有完成,等更新......

5、星系炸弹
题目描述

在X星系的广袤空间中漂浮着n个X星人造“炸弹”,每个炸弹都可以设定多少天之后爆炸。例如:阿尔法炸弹2015年1月1日放置,定时为15天,则它在2015年1月16日,星期五爆炸。

输入

第一行为n值,以后连续n行为炸弹放置日期(格式为 年-月-日)和定时天数(整型)。

输出

输出n行,每行为爆炸的准确日期(格式为 yyyy年mm月dd日 星期几),日期和星期之间用一个空格隔开。请严格按照格式书写,不能出现其它文字或符号。

提示信息:

星期的数据集合是【星期日、星期一、星期二、星期三、星期四、星期五、星期六】。1900年1月1日,是星期一。

样例输入

2
1999-9-9 800
2014-11-9 1000

样例输出

2001年11月17日 星期六
2017年08月05日 星期六

该题及为时间计算题,要注意对平年闰年的推导计算和星期的推导计算

代码源:

#include
void DAY(int year,int month,int day,int days)
{
    char week[7][10]={"星期一","星期二","星期三","星期四","星期五","星期六","星期日"}; 
    int monthday[12]={31,28,31,30,31,30,31,31,30,31,30,31}; 
    int i;
    int s=0,t;
    for(i=0;imonthday[month-1])
        {
            day=1;
            month++;
            if(month==13)
            {
                month=1;
                year++;
                if((year%4==0 && year%100!=0) ||year%400==0)
                {
                    monthday[1]=29;
                }
                else
                    monthday[1]=28;
            }
        }
    }
    if(month>9 && day>9)
    {
        printf("%d年%d月%d日 ",year,month,day);
    }
    if(month>9 && day<=9)
    {
        printf("%d年%d月0%d日 ",year,month,day);
    }
    if(month<=9 && day>9)
    {
        printf("%d年0%d月%d日 ",year,month,day);
    }
    else if(month<=9 && day<=9)
    {
        printf("%d年0%d月0%d日 ",year,month,day);
    }
    for(i=1990;i
6、字符串求解前缀
题目描述

给定n组字符串,每组两个字符串,以空格分开。找出这组两个字符串的公共前缀,并输出。

输入

第一行输入组数n,之后的n行,每行输入两个单词,这两个单词以空格分隔。

输出

输出n行,每行为对应组中两个单词的公共前缀,或者【无公共前缀】。

样例输入

2
come component
shanxi beijing

样例输出

com
无公共前缀

提示

待统计的数据个数不超过10对,每个字符串的长度不超过20。

代码源:

#include
#include
int main()
{
    int n;
    scanf("%d",&n);
    char str1[10];
    char str2[10];
    char str[10];
    int i,j,flag,t=0;
    while(n--)
    {
        scanf("%s %s",&str1,&str2);
        int len1=strlen(str1);
        int len2=strlen(str2);
            for(i=0;i
7、在指定位置增加图书信息
题目描述

一本图书的信息有: 编号、书名、作者、出版社、出版日期、价格。设计一个结构体类型描述图书信息,并实现输入多本(不超过20本)图书信息,存储在该结构体的数组变量中。在增加加一本图书到指定位置并输出增加后的结果。

输入

第一行输入图书的本数n。
以后的n行,每行输入一本图书的信息;每本图书信息的输入说明如下:输入时,各个信息之间空格间隔;编号为整数;书名、作者、出版社均为长度不超过30的字符串;出版日期的输入格式为yyyy-mm-dd,例如(2017-5-2);价格为实数。
第n+2行输入一个整数m,表示增加的图书将成为第m本图书。
第n+3行输入待增加图书的各项信息,格式同上。

输出

以列表方式输出增加后的结果:(注意,输出中除了汉字外,其他符号均为英文符号)
第一行输出标题行,分别输出:“编号”、“书名”、“作者”、“出版社”、“出版日期”、“价格”;相邻两项之间以一个空格间隔。(参见样例)
以后每行输出一本书,依次输出<编号>,<书名>,<作者>,<出版社>,<出版日期>,<价格(小数点后保留2位)>,相邻两项之间以一个空格间隔。(参见样例)

样例输入

3
2 数据结构 耿国华 高等教育出版社 2005-7-1 28.00
4 大学英语 LEE 清华出版社 1990-4-1 34.6
7 车来了 噼里啪啦 二十一世纪出版社 2008-9-9 18.50
3
1 高等数学 张三 高等教育出版社 1994-5-1 18.50

样例输出

编号 书名 作者 出版社 出版日期 价格
2 数据结构 耿国华 高等教育出版社 2005年7月1日 28.00
4 大学英语 LEE 清华出版社 1990年4月1日 34.60
1 高等数学 张三 高等教育出版社 1994年5月1日 18.50
7 车来了 噼里啪啦 二十一世纪出版社 2008年9月9日 18.50

这道题同第3题有些类似,但因为这道题增加了插入操作,所以我觉得可能用链表写会简单一点,但是我实在是链表不精通,所以这个题我依然用的是结构体数组的插入方法完成的,等后面如果我用链表完成了再来更新。

代码源:

#include
struct BOOK
{
    int num;
    char name[30];
    char editor[30];
    char pub[60];
    int year;
    int month;
    int day;
    float price;
};
int main()
{
    int n,m;
    scanf("%d",&n);
    struct BOOK book[10];
    struct BOOK t[10];
    int i,j;
    for(i=0;im-1)
        {
            t[i]=book[i-1];
        }
    }
    printf("编号 书名 作者 出版社 出版日期 价格\n");
    for(j=0;j
8、 黑色星期五
题目描述

有些西方人比较迷信,如果某个月的13号正好是星期五,他们就会觉得不太吉利,用古人的说法,就是“诸事不宜”。请你编写一个程序,统计出在某个特定的年份中,出现了多少次既是13号又是星期五的情形,以帮助你的迷信朋友解决难题。
说明:
(1)一年有365天,闰年有366天,所谓闰年,即能被4整除且不能被100整除的年份,或是既能被100整除也能被400整除的年份;
(2)已知1998年1月1日是星期四,用户输入的年份肯定大于或等于1998年。

输入

输入只有一行,即某个特定的年份(大于或等于1998年)。

输出

输出只有一行,即在这一年中,出现了多少次既是13号又是星期五的情形,格式为【****年有*个黑色星期五】。

样例输入

1998

样例输出

1998年有3个黑色星期五

该题思想同第五题

代码源:

#include
int DAY(int year)
{
//  char week[7][20]={"星期四","星期五","星期六","星期日","星期一","星期二","星期三"}; 
    int monthday[12]={31,28,31,30,31,30,31,31,30,31,30,31}; 
    int i,j,t=0,s=0;
    if((year%4==0 && year%100!=0) ||year%400==0)
    {
        monthday[1]=29;
    }
    else
        monthday[1]=28;
    for(i=1998;i
9.生日蜡烛
题目描述

某君从某年开始每年都举办一次生日party,并且每次都要吹熄与年龄相同根数的 蜡烛。现在算起来,他一共吹熄了N根蜡烛。请问,他从多少岁开始办生日party的,现在他多少岁?
例如:若N=236,因为236=26+27+28+29+30+31+32+33,所以,他从26岁开始办生日party,他现在33岁。

输入

输入一共吹熄的蜡烛数N。

输出

输出他办生日party的起止年龄数,以空格隔开;若有多种情况,输出起始年龄最小的一种情况。

样例输入

236

样例输出

26 33

代码源:

#include
int main()
{
    int i=1,j,sum=0;
    int n;
    scanf("%d",&n);
    while(sum!=n)
    {
        for(j=i;;j++)
        {
            sum=sum+j;
            if(sum==n)
            {
                printf("%d %d",i,j);
                break;
            }
            else if(sum>n)
            {
                sum=0;
                break;
            }
         } 
        i++;
    }
 } 
10、.特大整数的精确相加和相减
题目描述

特大整数用长整型也存不下,如果用双精度实型存储则会造成误差,可以用字符数组存储所有位,再按十进制由低到高逐位相加,同时考虑进位。

特别提示:

假设特大整数不超过30位。参与操作的数据中,被减数>减数。

算法分析:

1.初始化:将两个特大整数输入两个字符数组,将两个字符数组的各元素右移,使最低位的元素位置对齐,高位补0,为了存储最高位的进位,位数多的数最高位前也应补一个0。
2.从最低位对应的数组元素开始将数字字符转换为整型数据相加,因为数字字符‘0’对应的ASCII值是48,则:整型数据1+2,相当于 ('1'-48)+('2'-48),即'1'+'2'-96。
3.将和整除以10,余数就是该位的结果,并转换为字符(整型数据+48)存入该位,商就是进位数。
4.再对高一位对应的数组元素操作,将该位数字字符转换为整型相加,并与低位的进位数相加,将和整除以10,余数就是该位的结果,商就是本位的进位数。
5.重复4直到最高位。如果最高位相加时进位数大于0则将此进位数转换为字符存入最高位。

输入

第一行待运算的表达式个数n,之后连续的2n行每相邻得两行为一组。

输出

依次输出运算结果,共输出2n行。前n行为相加的运算结果;后n行为相减的运算结果,每个结果独占一行。

样例输入

3
123456789
23456789
999999999
999999999
1000000000
9999

样例输出

146913578
1999999998
1000009999
100000000
0
999990001

代码源:

#include
#include
#include
 
void swap(char target[]) {
    int i;
    int j;
    char temp;
 
    for(i = 0,j = strlen(target) - 1;i <= j;i++,j--) {
        temp = target[i];
        target[i] = target[j];
        target[j] = temp;
    }
}
 
void BigNumAdd(char a[],char b[]) {
    int i;
    char c[1001] = {0};
 
    swap(a);
    swap(b);
 
    for(i = 0;i < strlen(a) && i < strlen(b);i++) {
        c[i] += a[i] + b[i] - '0';
        if(c[i] - '0' >= 10){
            c[i] = c[i] - 10;
            c[i+1] = 1;
        }
    }
    
    if(strlen(a) == strlen(b)) {
        if(c[i] == 1) 
            c[i]='1';
    }
    
    if(strlen(a) > strlen(b)){
        if(c[i] == 1) {
            for(;i < strlen(a);i++){
                c[i] += a[i];
                if(c[i] - '0' >= 10) {
                    c[i] = c[i] - 10;
                    c[i+1] = 1;
                }
            }   
 
            if(c[i-1] == '0')
                c[i] = '1';
        }
        else { 
            for(;i < strlen(a);i++)
                c[i] = a[i];
        }
    }
 
    if(strlen(b) > strlen(a)){
        if(c[i]==1){
            for(;i < strlen(b);i++){
                c[i] += b[i];
                if(c[i] - '0' >= 10){
                    c[i] = c[i] - 10;
                    c[i+1] = 1;
                }
            }
            if(c[i] == 1)
                c[i] = '1';
        } else { 
            for(;i < strlen(b);i++)
                c[i] = b[i];
        }
    }
    swap(c);
 
    printf("%s\n",c);
}
 
void BigNumChange(char *str1, char *str2) {
    int len1 = strlen(str1);  
    int len2 = strlen(str2);  
    int i;  
    int *num1 = (int*)malloc(len1*sizeof(int));  
    int *num2 = (int*)malloc(len1*sizeof(int));  
 
    if(str1 == NULL || str2 == NULL) 
        return;  
    
    for (i = 0; i < len1; i++)  
    {  
        num1[i] = num2[i] = 0;  
    }  
    for (i = len1 - 1; i >= 0; i--)  
    {  
        num1[len1 - 1 - i] = str1[i] - '0';  
    }  
    for (i = len2 - 1; i >= 0; i--)  
    {  
        num2[len2-1-i] = str2[i] - '0';  
    }  
    for (i = 0; i < len1; i++)  
    {  
        num1[i] = num1[i] - num2[i];  
        if(num1[i] < 0)  
        {  
            num1[i] = num1[i] + 10;  
            num1[i+1] = num1[i+1] - 1;  
        }  
    }  
    for (i = len1-1; i>=0 && num1[i] == 0; i--)  
        ;  
    if(i >= 0)  
        for (; i >= 0; i--)  
        {  
            printf("%d",num1[i]);  
        }  
    else  
        printf("0");  
 
}  
 
int main(void) {
    int n;
    char a[100][100];
    int i;
    int len1;
    int len2;
 
    scanf("%d",&n);
    for(i = 0;i < 2*n;i++) {
        scanf("%s",a[i]);
    }
    
    for(i = 0;i < 2*n;i += 2) {
        BigNumAdd(a[i],a[i+1]);
    }
 
    for(i = 0;i < 2*n;i++) {
        swap(a[i]);
    }
 
    for(i = 0;i < 2*n;i += 2) {
        len1 = strlen(a[i]);
        len2 = strlen(a[i+1]);
        if(len1 > len2) {
            BigNumChange(a[i],a[i+1]);
        } else if(len1 < len2) {
            printf("-");
            BigNumChange(a[i+1],a[i]);
        } else {
            if(strcmp(a[i],a[i+1]) >= 0) {
                BigNumChange(a[i],a[i+1]);
            } else {
                printf("-");
                BigNumChange(a[i+1],a[i]);
            }
        }
        printf("\n");
    }
    return 0;
}

你可能感兴趣的:(2019“西邮杯”初赛题解)