2018“西邮杯”初赛题解

1.加法变乘法

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

例如:当X为1225,Y为2015时
因为:1+2+3+ ... + 49 = 1225
     且1+2+3+...+10*11+12+...+27*28+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<stdio.h>
void fun(int x,int y) {
	int i;
	int j;
	int tmp = 0;
	int res = 0;
	int flag = 1;
	for(i = 2; i <= 10000; i++) { 
		for(j = i+2; j <= 10000; j++) {    
			tmp=x-i*2-j*2-2;
			res=y-i*(i+1)-j*(j+1);
			 if(res == tmp) {    
		    	           printf("(%d,%d)",i ,j );  
			           flag = 0;
			}
		}
	    }
	if(flag == 1){
	    	printf("NONE");
	}
	printf("\n");
}


int main(void) {
	int n;
	int X;
	int Y;
	
        scanf("%d",&n);
	while(n--) {
		scanf("%d %d",&X,&Y);
		fun(X,Y);  
	}
	return 0;
}

2.核桃的数量

小张是软件项目经理,他带领3个开发组。工期紧,今天都在加班呢。
为鼓舞士气,小张打算给每个组发一袋核桃(据传言能补脑)。
他的要求是:
(1)各组的核桃数量必须相同;
(2)各组内必须能平分核桃(当然是不能打碎的)
(3)尽量提供满足1,2条件的最小数量

输入

输入包含三个正整数a,b,c,表示每个组正在加班的人数,用空格分开 (a,b,c均小于30)

输出

输出一个正整数,表示每袋中核桃的数量,不要输出多余的信息。

样例

30 12 9
180

题解:此题即求三个数的最小公倍数。

源代码

#include<stdio.h>
int max(int a,int b,int c)  
{
  if(a>b&&a>c)           
      return a;           
  else if(b>a&&b>c)       
      return b;           
  else
      return c;           
}
int  main()
{
  int x,y,z,i,j,k;
  scanf("%d%d%d",&x,&y,&z); 
  k = max(x,y,z);          
  i= 1;
  while(1)                 
  { 
    j = k * i;
    if((j%x==0)&&(j%y==0)&&(j%z==0)) 
        break;
    i++;
  }
  printf("%d\n",j);
  return 0; 
}

3.翻硬币

小明正在玩一个“翻硬币”的游戏,桌上放着排成一排的若干硬币。
我们用 * 表示正面, 用 o 表示反面(是小写字母,不是零)。
例如,可能情形是:**oo***oooo,
如果同时翻转左边的两个硬币,则变为:oooo***oooo。

现在小明的问题是:如果已知了初始状态和要达到的目标状态,每次只能同时翻转相邻的两个硬币
那么对特定的局面,最少要翻动多少次呢?
我们约定:把翻动相邻的两个硬币叫做一步操作。

输入

两行等长的字符串,分别表示初始状态和要达到的目标状态,每行的长度<1000。

输出

一个整数,表示最小操作步数。

样例

**********
o****o****
5

题解:如果初始状态和目标状态不一致则同时翻转两个相邻的硬币,每翻转一次计数器加1。

源代码

#include<stdio.h>
#include<string.h> 
#define maxn 1002
void change(char str[],int i)
{
     str[i]=str[i]=='*'?'o':'*';
}
int main()
{
    char str1[maxn],str2[maxn];
    scanf("%s%s",str1,str2);
    int i=0,tot=0;
    int l=strlen(str1);
     while(i < l-1)
    {
       if(str2[i]!=str1[i])
       {
          tot++;
          change(str2,i);
          change(str2,i+1);
       }
       i++;
    }
    printf("%d\n",tot);
    return 0;
}

4.格式打印

编写程序实现将一段文章格式化打印出来。打印时每行的长度为20个字符。

输入

该段文章长度<=500,单词的数量<=100。

以回车作为该段文章的输入结束。

输出

如果一行的最后一个单词超过了本行的20个字符的范围,则应把它移到下一行;
如果某行仅一个单词,则在该单词结束处直接换行;
否则在每行最后一个单词前增加一些空格,以便使每行的末尾准确地显示在第20个位置处。

样例

The relationship between XML functional dependencies and XML keys are also discussed.

The     relationship
between          XML
functional
dependencies     and
XML keys are    also
discussed.

题解

先用gets()接收,然后用二维字符串数组存储单词。然后用start和end确定每行首和下一行开始的单词下标。多于一个注意要右对齐,计算空格的个数。

源代码

#include<stdio.h>    
#include<string.h>    
int main()
 {    
    char a[10001];    
    char word[101][100];    
    char ch;    
    int i;    
    int length;    
    gets(a);    
    int len = strlen(a);      
    int count = 0;      
    int k = 0;    
    for(i = 0;i < len;i++) {      
        if(a[i] != ' ') {      
            word[count][k] = a[i];      
            k++;              
        } else {      
            k = 0;      
            count++;      
        }      
    }      
    count=count++;     
    int start = 0;    
    length = 0;    
    int end = -1;  
    while(end != count) {    
        end = -1;    
            
        if(length != 1) {    
            length = 0;    
        }    
            
        for(i = start;i < count;i++) {    
            length += strlen(word[i]);    
            if(length > 20) {    
                end = i;    
                break;    
            }    
            length++;    
        }    
            
        if(end == -1)      
            end = count;      
                
        if(end - start == 1) {      
            printf("%s",word[start]);      
            length = 1;      
        } else {    
            int space = 21;    
            for(i = start;i < end;i++) {    
                space -= strlen(word[i]);    
                space--;    
            }    
            for(i = start;i < end - 1;i++) {    
                printf("%s ",word[i]);    
            }    
            for(i = 0;i < space;i++) {    
                printf(" ");    
            }    
            printf("%s",word[end-1]);    
        }     
         printf("\n");    
        start = end;    
    }    
         return 0;    
}    

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<stdio.h>  
void fun(int days,int year,int month,int day) {  
    char week[7][28] = {"星期一","星期二","星期三","星期四","星期五","星期六","星期日"};  
    int monthDays[12] = {31,28,31,30,31,30,31,31,30,31,30,31};     
    int i;    
    int s = 0;  
    int flag_1 = 0;  
    int flag_2 = 0;  
    for(i=0;i<days;i++) {    
        day++;    
        if(day > monthDays[month-1])    
        {    
            day=1;    
            month++;    
            if(month > 12)    
            {    
                month=1;    
                year++;    
                if((year%400==0) ||(year%4==0 && year%100!=0))    
                    monthDays[1] = 29;    
                else    
                    monthDays[1] = 28;    
            }    
        }    
    }    
    if(month > 9)  
        flag_1 = 1;  
    if(day > 9)  
        flag_2 = 1;  
    if(flag_1 == 1 && flag_2 == 1) {  
        printf("%d年%d月%d日 ",year,month,day);  
    } else if(flag_1 == 0 && flag_2 == 1) {  
        printf("%d年0%d月%d日 ",year,month,day);  
    } else if(flag_1 == 1 && flag_2 == 0) {  
        printf("%d年%d月0%d日 ",year,month,day);  
    } else if(flag_1 == 0 && flag_2 == 0) {  
        printf("%d年0%d月0%d日 ",year,month,day);  
    }  
  	 if(year >= 1990) {  
        for(i = 1990;i < year;i++) {  
            if((i%400 == 0) || (i%4 == 0 && i%100 != 0))   
                s += 366;     
            else  
                s += 365;  
        }  
        if((year%400==0) ||(year%4==0 && year%100!=0))    
            monthDays[1] = 29;    
        else    
            monthDays[1] = 28;   
        for(i = 0;i < month - 1;i++) {  
            s += monthDays[i];  
        }  
        s += day - 1;  
        printf("%s",week[s%7]);  
    } else {  
        for(i = 1990;i > year;i--) {  
            if((i%400 == 0) || (i%4 == 0 && i%100 != 0))   
                s += 366;     
            else  
                s += 365;  
        }   
        if((year%400==0) ||(year%4==0 && year%100!=0))    
            monthDays[1] = 29;    
        else    
            monthDays[1] = 28;   
        for(i = 12;i > month;i--) {  
            s += monthDays[i - 1];  
        }  
        s += monthDays[month] - day + 1;  
        printf("%s",week[s%7]);  
    }  
}  
int main(void) {  
    int n;  
    int year;  
    int month;  
    int day;  
    int days;  
	scanf("%d",&n);  
    while(n--) {  
        scanf("%d-%d-%d %d",&year,&month,&day,&days);  
        fun(days,year,month,day);  
        printf("\n");  
    }  
  
    return 0;  
}  

6.特大整数的相加和相减

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

特别提示:假设特大整数不超过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<stdio.h>
#include<string.h>
#include<stdlib.h>
 
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;
}



7.可逆素数

若将某一素数的各位数字顺序颠倒后得到的数仍然是素数,则次素数称为可逆素数。

判断给定的n个数据是否是可逆素数。

输入

第一行为n值,第二行输入n个数字,以空格间隔。

输出

输出n行,每一行的格式为【***是可逆素数】(或者【***是素数,但不是可逆素数】,用中文逗号隔开,或者【***不是素数】)。

请严格按照格式书写,不能出现其它文字或符号。

特别说明:待判断的数据个数不超过10个。

样例

3
23 31 18
23是素数,但不是可逆素数
31是可逆素数
18不是素数

题解

先判断是否为素数,再将此数颠倒顺序,判断是否为可你素数(素数的判断条件:除1和他本身以外没有其他的因数)

源代码

#include<stdio.h>  
  
int is_Prime(int n);  
  
int is_Prime(int n) {  
    int i;  
    if(n <= 1) {  
        return 0;  
    }else if(n == 2) {  
        return 1;  
    } else {  
        for(i = 2;i < n;i++) {  //此处判断可简化为n/2,或者根号n
            if(n % i == 0){  
                break;    
            }  
        }  
        if(i == n){  
                return 1;  
        }else {  
            return 0;  
        }  
    }  
}  
  
int swap(int n) {  
    int result = 0;    
    int i;      
      
    if(n == 0) {    
        return result;    
    }      
        
    while(n > 0) {    
        i = n % 10;    
        n = n / 10;    
            
        result = result * 10 + i;           
    }    
        
    return result;   
}  
  
int main(void) {  
    int n;  
    int a[11];  
    int flag_1;  
    int flag_2;  
    int t;  
    int i;  
  
    scanf("%d",&n);  
    for(i = 0;i < n;i++) {  
        scanf("%d",&a[i]);  
    }  
    for(i = 0;i < n;i++) {  
        flag_1 = 0;  
        flag_2 = 0;  
        if(is_Prime(a[i])) {  
            flag_1 = 1;  
        }  
        t = swap(a[i]);  
        if(is_Prime(t)) {  
            flag_2 = 1;  
        }  
        if(flag_1 == 1 && flag_2 == 1) {  
            printf("%d是可逆素数\n",a[i]);  
        } else if(flag_2 == 0 && flag_1) {  
            printf("%d是素数,但不是可逆素数\n",a[i]);  
        } else {  
            printf("%d不是素数\n",a[i]);  
        }  
    }  
  
    return 0;  
}  

8.生日蜡烛

某君从某年开始每年都举办一次生日party,并且每次都要吹熄与年龄相同根数的蜡烛,设他一共吹熄了n根蜡烛。 
请问:他从多少岁开始过生日party的? 

输入

输入一共吹的蜡烛个数n

输出

开始过生日的年龄 现在的年龄

样例

236
26 33


源代码

#include <stdio.h>
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)
            {
                sum = 0;
                break;
            }
            else if(sum == n&& i <n)
            {
                printf("%d %d", i,j);
                break;
            }
        }
        i++;
    }
	return 0;
}

9.移动字母

2×3=6个方格中放入ABCDE五个字母,右下角的那个格空着。如图所示。

1

和空格子相邻的格子中的字母可以移动到空格中,比如,图中的C和E就可以移动,移动后的局面分别是:

A B
D E C

A B C
D E

为了表示方便,我们把6个格子中字母配置用一个串表示出来,比如上边的两种局面分别表示为:

AB*DEC
ABCD*E

题目的要求是:请编写程序,由用户输入若干表示局面的串,程序通过计算,输出是否能通过对初始状态经过若干次移动到达该状态。可以实现输出1,否则输出0。初始状态为:ABCDE*

输入

一个整数n
n行的状态

输出

n行0或1

样例

3
ABCDE*
AB*DEC
CAED*B
1
1
0


源代码

#include<stdio.h>  
#include<string.h>  
int vis[6];
int TF[100],count;  
char temp[]="ABCDE*"; 
void Getstar(char array[],int *row,int *column)  
{  
	int i;
    for (i = 0; i < 6; i++)  
    {  
        if (array[i] == '*')  
        {  
            *row = i - 3 < 0 ? 0 : 1;  
            *column = i % 3;  
        }  
    }  
}  
void Print(int n) 
{  
	int i;
    for (i = 0; i < n; i++)  
    {  
        printf("%d\n",TF[i]);  
    }  
}  
void swap(char *a,char *b) 
{  
    char T = *a;  
    *a = *b;  
    *b = T;  
}  
void fun(char *cur,int row,int column)
{  
    int i,x,y;  
    int a[4][2]={{1,0},{0,1},{-1,0},{0,-1}};  
    if(!strcmp(cur,temp))  
    {  
        TF[count] = 1;  
        return;  
    }  
    else  
    {  
        for(i = 0; i < 4; i++)
        {  
            x = row + a[i][0];  
            y = column + a[i][1];  
            if((x >= 0 && x <= 1) && (y >= 0 && y <= 2) && !vis[3 * x + y])  
            {  
                swap(cur + 3 * row + column,cur + 3 * x + y);  
                vis[3 * x + y] = 1;  
                fun(cur,x,y);  
                swap(cur + 3 * row + column,cur + 3 * x + y);
                vis[3 * x + y] = 0;  
            }  
        }     
    }  
}     
int main()  
{  
    int n,row,column,i;  
    char array[7];  
    scanf("%d",&n);  
    i = n;  
    while (i)  
    {  
        scanf("%s",array);  
        Getstar(array,&row,&column);  
        fun(array,row,column);  
        count++;  
        i--;  
    }  
    Print(n);  
    return 0;  
}  

10.按价格排序并输出

一道简单的结构体排序输出问题  ,原题看不见了,原谅我语文不好,自行看代码吧。

注:使用结构体的时候一定要分配空间不然容易乱码

源代码

#include <stdio.h>
#include <malloc.h>
struct Student
{
    int num;
    float price;
    char name[100];
    char editor[100];
	char chubanshe[100];
	int year;
	int month;
	int day;
};
int main(void)
{
    struct Student * pst;
    struct Student tst;
    int i, j, m, n;
    int len;
    scanf("%d", &len);
    pst= (struct Student *)malloc(len * sizeof(struct Student));
    for(i = 0; i<len; i++)
    {
    	scanf("%d", &pst[i].num);
        scanf("%s", pst[i].name);
        scanf("%s", pst[i].editor);
        scanf("%s", pst[i].chubanshe);
        scanf("%d-%d-%d", &pst[i].year,&pst[i].month,&pst[i].day);
        scanf("%f", &pst[i].price);
        
    }
 for(m=0; m<len; m++)
    {
        for(n = 0; n<len-1-m;n++)
        if(pst[n].price > pst[n+1].price)
        {
            tst = pst[n];
            pst[n] = pst[n+1];
            pst[n+1] = tst;
        }
  }
  	printf("编号 书名 作者 出版社 出版日期 价格\n");
	  for(j = 0; j<len; j++)
    {
    	printf("%d ", pst[j].num);
        printf("%s ", pst[j].name);
        printf("%s ", pst[j].editor);
        printf("%s ", pst[j].chubanshe);
        printf("%d年%d月%d日 ", pst[j].year,pst[j].month,pst[j].day);
        printf("%.2f", pst[j].price);
        printf("\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40384370/article/details/80852088