西邮杯初赛

来源:互联网 发布:一元秒杀包邮 淘宝 编辑:程序博客网 时间:2024/06/05 04:15

问题 A: CONTEST1.加法变乘法(by YAN)

时间限制: 10 Sec  内存限制: 256 MB
提交: 254  解决: 115
[提交][状态][讨论版]

题目描述

已知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”)。请严格按照格式书写,不能出现其它文字或符号。

样例输入

31225 20151224 20151275 2065

样例输出

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

双重循环暴力

#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++) { tmp = res = x - (i+(i-1)) + i*(i-1);for(j = i+2; j <= 10000; j++) {    res = tmp - (j + (j-1)) + j * (j-1);    if(res == y) {       printf("(%d,%d)",i - 1,j - 1);     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;}

问题 B: CONTEST2.核桃的数量(BY YAN)

时间限制: 10 Sec  内存限制: 256 MB
提交: 760  解决: 597
[提交][状态][讨论版]

题目描述

小张是软件项目经理,他带领3个开发组。工期紧,今天都在加班呢。为鼓舞士气,小张打算给每个组发一袋核桃(据传言能补脑)。他的要求是:

(1)各组的核桃数量必须相同;

(2)各组内必须能平分核桃(当然是不能打碎的)

(3)尽量提供满足1,2条件的最小数量(节约闹革命嘛)

输入

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

输出

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

样例输入

30 12 9

样例输出

180


求三个数的最小公倍数

#include<stdio.h>int fun(int x,int y);  int fun(int x,int y) {      int t;int d;      if(y > x) {          t = x;          x = y;          y = t;      }      while(y != 0) {          d = y;          y = x%y;          x = d;      }      return x;  }  int main(void) {      int x;int y;int z;int n;int m;      scanf("%d %d %d",&x,&y,&z);      m = x * y / fun(x,y);      n = m * z/ fun(z,m);      printf("%d\n",n);      return 0;  }    

问题 C: CONTEST3.移动距离(BY YAN)

时间限制: 10 Sec  内存限制: 256 MB
提交: 758  解决: 332
[提交][状态][讨论版]

题目描述

X星球居民小区的楼房全是一样的,并且按矩阵样式排列。其楼房的编号为1,2,3...当排满一行时,从下一行相邻的楼往反方向排号。

例如:当小区排号宽度为6时,开始情形如下:

1   2   3   4   5   6

12  11  10  9   8   7

13  14  15  .....

问题是:已知了两个楼号m和n,需要求出它们之间的最短移动距离(不能斜线方向移动)

输入

输入为3个整数w m n,空格分开,都在1到10000范围内。

w为排号宽度,m,n为待计算的楼号。

输出

输出一个整数,表示m n 两楼间最短移动距离。

样例输入

6 8 2

样例输出

4

求点的坐标,奇数行正序,偶数行逆序,曼哈顿距离(横坐标之差绝对值+纵坐标之差绝对值)

#include<stdio.h>#include<math.h>typedef struct node {int x;int y;}node;node fun(int w,int n) {node tmp;tmp.x = (n-1) / w + 1;      tmp.y = n % w;        if (tmp.y == 0) tmp.y = w;      if (tmp.x % 2 == 0) {         tmp.y = w - tmp.y + 1;      }  return tmp;}int main(void) {node tmp_1;node tmp_2;int w;int m;int n;int res;scanf("%d %d %d",&w,&m,&n);tmp_1 = fun(w,m);tmp_2 = fun(w,n);res = abs(tmp_1.x - tmp_2.x) + abs(tmp_1.y - tmp_2.y);printf("%d\n",res);return 0;}


问题 D: CONTEST4.翻硬币(BY YAN)

时间限制: 10 Sec  内存限制: 256 MB
提交: 458  解决: 293
[提交][状态][讨论版]

题目描述

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

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

我们约定:把翻动相邻的两个硬币叫做一步操作。

输入

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

输出

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

样例输入

**********o****o****

样例输出

5

从左到右遇到不同的就翻一次,就会得到答案

#include<stdio.h>#include<string.h>char a[1001];char b[1001];void fun(int i) {    if(a[i] == '*')          a[i] = 'o';      else          a[i] = '*';      if(a[i+1] != 0) {          if(a[i+1] == 'o')              a[i+1] = '*';          else              a[i+1] = 'o';      }  }int main(void) {int count = 0;int len;int i;gets(a);gets(b);len = strlen(a);for(i = 0;i < len;i++) {if(a[i] != b[i]) {fun(i);count++;}}printf("%d\n",count);return 0;}

问题 E: CONTEST5.字符统计(BY YAN)

时间限制: 10 Sec  内存限制: 256 MB
提交: 445  解决: 297
[提交][状态][讨论版]

题目描述

编写程序接收从键盘输入的n个字符串(1<n<=10),然后实现下列功能:

(1)输出字符串的长度;

(2)输出字符串所包含的单词的数量;

(3)统计该字符串包含的大写字母、小写字母、数字、空格和其他字符的数量并输出。

输入

第一行为n值,以后连续n行为待统计的字符串,每行的长度<100。

每个单词之间用一个空格隔开,或者用一个标点加一个空格隔开。

输出

输出n行,每行是7个整数,依次表示:字符串长度、单词数量、大写字母数量、小写字母数量、数字数量、空格数量、其他字符数量。每个数字以空格隔开,每行最后一个数字后面没有空格。

样例输入

3There are 166 students in the C programming contest.Congratulation, you receive nice scores in this test, please continue.I am very fond of learning advanced language program design courses.

样例输出

52 9 2 38 3 8 170 10 1 57 0 9 368 11 1 56 0 10 1

单词数=空格数+1

#include<stdio.h>#include<string.h>int main(void) {char a[20][101];int len;int kongge;int shuzi;int daxie;int xiaoxie;int qita;int n;int j;int i;scanf("%d",&n);getchar();for(i = 0;i < n;i++) {gets(a[i]);}for(i = 0;i < n;i++) {kongge = 0;shuzi = 0;daxie = 0;xiaoxie = 0;qita = 0;len = strlen(a[i]);for(j = 0;j < len;j++) {if(a[i][j] == ' ')     kongge++;              else if(a[i][j] >= 'a' && a[i][j] <= 'z')   xiaoxie++;              else if(a[i][j] >= 'A' && a[i][j] <= 'Z')   daxie++;              else if(a[i][j] >= '0' && a[i][j] <= '9')   shuzi++;              else  qita++;  }printf("%d %d %d %d %d %d %d",len+1,kongge + 1,daxie,xiaoxie,shuzi,kongge,qita);if(i != n-1) printf("\n"); }return 0;}






问题 F: CONTEST6.格式打印(by YAN)

时间限制: 10 Sec  内存限制: 256 MB
提交: 72  解决: 21
[提交][状态][讨论版]

题目描述

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

输入

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

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

输出

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

样例输入

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

样例输出

The relationshipbetween XMLfunctionaldependencies andXML keys are alsodiscussed.

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

#include<stdio.h>  #include<string.h>    int main(void) {      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 + 1;       /*//这样出现段错误,求解     ch = getchar();       while(ch != '\n'){              while(ch == ' ') {             ch = getchar();         }         i = 0;         while( (ch != ' ') && (ch != '\n')) {              word[count][i++] = ch;              ch = getchar();          }          word[count][i] = 0;         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;  }  





问题 G: CONTEST7.可逆素数(BY YAN)

时间限制: 10 Sec  内存限制: 256 MB
提交: 818  解决: 360
[提交][状态][讨论版]

题目描述

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

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

输入

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

输出

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

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

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

样例输入

323 31 18

样例输出

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


#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++) {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;}





问题 H: CONTEST8.星系炸弹(by YAN)

时间限制: 10 Sec  内存限制: 256 MB
提交: 104  解决: 24
[提交][状态][讨论版]

题目描述

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

输入

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

输出

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

提示信息:星期数据集合是【星期、星期一、星期二、星期三、星期四、星期五、星期六】1900年1月1日,是星期一。

样例输入

21999-9-9 8002014-11-9 1000

样例输出

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

日期累加,月和年进位。再求日期与1990年1月1日的天数差值,和7取余。注意星期数组的大小。

#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;elses += 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;elses += 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;}



问题 I: CONTEST9.特殊回文数(BY YAN)

时间限制: 10 Sec  内存限制: 256 MB
提交: 745  解决: 203
[提交][状态][讨论版]

题目描述

123321是一个非常特殊的数,它从左边读和从右边读是一样的。输入一个正整数n, 编程求所有这样的五位和六位十进制数,满足各位数字之和等于n (1<=n<=54)。

输入

输入一个正整数n。

输出

若特殊回文数的个数<=10,则按从小到大的顺序输出满足条件的特殊回文数,每个数字占一行。

若特殊回文数的个数>10,则仅输出总个数。

样例输入

52

样例输出

899998989989998899

先判断是不是回文数,再判断是否满足条件。用一个数组存储,count小于等于10,输出数组,大于10,输出count。

#include<stdio.h>int h[10001];void fun(int n) {      int i;    int j;    int sum;    int temp;    int len;      int a,b,c;  int count = 0;j = 0;    for(i = 10000;i < 1000000;++i) {          sum = 0;          temp = i;          len = 0;          while(temp != 0) {              sum = sum * 10 + temp % 10;              temp = temp/10;              len++;           }          if(sum == i){              a = i % 10;            b = i / 10 % 10;            c = i / 100 % 10;                          if(5 == len) {                  if(n==(2*a + 2*b + c)) {                      h[j++] = i;count++;                 }               }              if(6 == len) {                  if(n == (2*a + 2*b + 2*c)) {  h[j++] = i;count++;                  }              }          }      }  if(count <= 10) {for(i = 0;i < count;i++) {printf("%d\n",h[i]);}} else {printf("%d\n",count);}}  int main(void) {int n;      scanf("%d",&n);      fun(n);      return 0; }



问题 J: CONTEST10.特大整数的精确相加和相减(by YAN)

时间限制: 10 Sec  内存限制: 512 MB
提交: 49  解决: 21
[提交][状态][讨论版]

题目描述

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

特别提示:假设特大整数不超过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行为相减的运算结果,每个结果独占一行。

样例输入

31234567892345678999999999999999999910000000009999

样例输出

146913578199999999810000099991000000000999990001


模拟竖式的手工过程


#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;}










最后推荐一个大佬的题解http://blog.csdn.net/hepangda/article/details/73431191 大笑