[关闭]
@xingxing 2016-12-08T14:49:49.000000Z 字数 7574 阅读 860

第一次作业

题解


[题目][A]

Design Tutorial: Learn from Math

题目大意:
给定一个n(12<=n<=10^6),输出符合条件的两个合数x,y,要求:x+y=n。

解题思路:
要满足x+y=n,即一个数x大于等于n/2,一个数y小于等于n/2,列举x和y,然后分别对x,y判断是否为合数。
时间复杂度O(n√n),空间复杂度(1)。

AC代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. using namespace std;
  6. int solve(int m)
  7. {
  8. int i;
  9. for(i = 2;i <= (int)sqrt(m);i++)
  10. {
  11. if(m % i == 0)
  12. {
  13. return 1;
  14. }
  15. }
  16. return 0;
  17. }
  18. int main()
  19. {
  20. int n;
  21. int i;
  22. while(scanf("%d",&n) != EOF)
  23. {
  24. for(i = n/2;i > 1;i--)
  25. {
  26. if(solve(i) && solve(n-i))
  27. {
  28. printf("%d %d\n",i,n-i);
  29. break;
  30. }
  31. }
  32. }
  33. return 0;
  34. }

[题目][B]

Design Tutorial: Learn from Life

题目大意:
给出乘客数n和电梯一次性最大载客量k(1<=n,k<=2000),以及n个乘客到达的目标楼层fi,(2<=f[i]<=2000),电梯用1s上一层楼,人数载量与电梯运行时间无关。初始时,人们都在第一层,求出最少时间能把所有人都运完,并且电梯又回到一楼。

解题思路:
电梯初始时在一楼,最后也要回到一楼,即每次运完乘客都要回到一楼继续运。而无论如何,最高楼层的人是要通过电梯过去的,所以当前要用的最少时间要以最高楼层的人到达的楼数来决定。所以尽可能把高楼层的乘客运完,即对目标楼层数按降序排序,从大到小,每次不超过k的限度运。
时间复杂度O(n),空间复杂度O(1)。

AC代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <algorithm>
  5. using namespace std;
  6. int f[2016];
  7. int main()
  8. {
  9. int n,k;
  10. int i;
  11. int ans;
  12. while(scanf("%d %d",&n,&k) != EOF)
  13. {
  14. ans = 0;
  15. for(i = 0;i < n;i++)
  16. {
  17. scanf("%d",&f[i]);
  18. }
  19. sort(f,f+n);
  20. if(n >= k)
  21. {
  22. for(i = n-1; i >= 0 && i+1 >= k;i -= k)
  23. {
  24. ans += 2*(f[i] - 1);
  25. }
  26. if(i+1 < k && i >= 0)
  27. {
  28. ans += (f[i]-1)*2;
  29. }
  30. }
  31. else
  32. {
  33. ans += 2*(f[n-1]-1);
  34. }
  35. printf("%d\n",ans);
  36. }
  37. return 0;
  38. }

[题目][C]

Design Tutorial: Make It Nondeterministic

题目大意:
给出n个人(1<=n<=10^5)的名和姓,其中每个人的姓fi和名si由只含小写字母的字符串组成(1<=|fi|,|si|<=50),并且这2n个姓、名互不相同。接着给出排列好的n个数据pi(1<=pi<=n)。判断这n个人的姓或名能否按字典序以所给出的数据列排序。

解题思路:
贪心。要尽可能满足所给出数据列的字典序,排在前面的人,应该选较小的名或姓作为它的handle。即,选择p1姓或名的最小字典序的,作为h1(p1的handle),然后每次判断一下后一个pi+1较大的字符串是否大于pi的字符串,尽可能选择pi+1较小的字符串作为hi+1,把满足要求的可能性扩大到最大。当某一时刻,hi比pi+1最小的字符串还大时,此时不能得到与数据列相吻合的字典序。
时间复杂度O(n),空间复杂度O(1)。

AC代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cstring>
  5. using namespace std;
  6. const int maxx = 123456;
  7. typedef struct name
  8. {
  9. char f[60],s[60];
  10. int flag;
  11. }person;
  12. person a[maxx];
  13. int main()
  14. {
  15. //freopen("in.txt","r",stdin);
  16. int n;
  17. int i;
  18. int num;
  19. char temp[60];
  20. int flag1 = 0;
  21. scanf("%d",&n);
  22. for(i = 0;i < n;i++)
  23. {
  24. getchar();
  25. scanf("%s",a[i].f);
  26. getchar();
  27. scanf("%s",a[i].s);
  28. if(strcmp(a[i].f,a[i].s) >= 0) a[i].flag = 1;
  29. else a[i].flag = 0;
  30. }
  31. for(i = 0;i < n;i++)
  32. {
  33. scanf("%d",&num);
  34. if(i == 0 && a[num-1].flag == 1)
  35. {
  36. strcpy(temp,a[num-1].s);
  37. }
  38. else if(i == 0 && a[num-1].flag == 0)
  39. strcpy(temp,a[num-1].f);
  40. if(i != 0)
  41. {
  42. if(a[num-1].flag == 1)
  43. {
  44. if(strcmp(temp,a[num-1].f) >= 0)
  45. flag1 = 1;
  46. else
  47. {
  48. if(strcmp(temp,a[num-1].s) >= 0)
  49. strcpy(temp,a[num-1].f);
  50. else strcpy(temp,a[num-1].s);
  51. }
  52. }
  53. else
  54. {
  55. if(strcmp(temp,a[num-1].s) >= 0) flag1 = 1;
  56. else
  57. {
  58. if(strcmp(temp,a[num-1].f) >= 0)
  59. strcpy(temp,a[num-1].s);
  60. else strcpy(temp,a[num-1].f);
  61. }
  62. }
  63. }
  64. }
  65. if(flag1 == 1) printf("NO\n");
  66. else printf("YES\n");
  67. return 0;
  68. }

[题目][E]

MUH and Sticks

题目大意:
给出6个数li(1<=li<=9),判断满足以下哪个条件:
(1)其中4个数相同,另外2个数一大一小,这两个数和另外的4个数没有绝对的大小关系时,输出Bear;
(2)4个数相同,另外2个数相等,这两个数和另外的4个数没有绝对的大小关系,此时输出Elephant;
(3)其余情况输出Alien.

解题思路:
因为6个数中,只有一组4个数相同,不会再有其他4个数相同的情况,所以先选出相同的四个数,再来判断剩下的2个数之间的关系。两个数只有两种关系,要么相等,要么不等,即在有4个数相同的前提下,分别为1和2的情况。当无法选出4个相同数时,此时为情况3。把i数字读入后,将个数计入ai。
时间复杂度O(1),空间复杂度O(1)。

AC代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cstring>
  5. using namespace std;
  6. int a[20];
  7. int main()
  8. {
  9. int i;
  10. int len;
  11. int flag1,flag2;
  12. flag1 = 0,flag2 = 0;
  13. for(i = 0;i < 6;i++)
  14. {
  15. scanf("%d",&len);
  16. a[len]++;
  17. }
  18. for(i = 1; i <= 9; i++)
  19. {
  20. if(a[i] == 4)
  21. {
  22. flag1 = 1;
  23. }
  24. if(a[i] == 2)
  25. {
  26. flag2 = 1;
  27. }
  28. if(a[i] == 6)
  29. {
  30. flag1 = 1;
  31. flag2 = 1;
  32. }
  33. if(a[i] == 5)
  34. {
  35. flag1 = 1;
  36. flag2 = 0;
  37. }
  38. }
  39. if(flag1 && flag2)
  40. printf("Elephant\n");
  41. else if(flag1 && flag2 == 0)
  42. printf("Bear\n");
  43. else printf("Alien\n");
  44. return 0;
  45. }

[题目][F]

题目大意:
给出n(1<=n<=2000)个任务的难度hi(1<=hi<=2000).将n个任务按难度排序输出,当有相同难度的任务时,可以交换序号从而产生难度相同,而序列不同的几种方案。输出其中3种方案的序列,若没有3个则输出NO。

解题思路:
因为要输出3组不同的序列,即可以只考虑(1)同一个难度有3个及以上的数量;或者(2)2个相同难度的任务组数为2的,有2组及以上。把难度i的任务存入a[i]数组中,并保存总共的该难度的任务数量以及对应的序号。然后遍历这个结构体数组,看是否有3个及以上的难度任务,和2组以上2个某个难度的任务。如果符合情况1,则将大于或等于3的难度值的序号,取其中三个,排列输出三种,其余该难度下多的直接输出,其他的序号直接输出。整体输出保持不递减的顺序,同时注意输出空格的格式,如果为输出的第一个数,则数字前没有空格,否则每个数字前都有一个空格。如果符合情况2,则将其他n-2个难度值的任务序号,按难度值递增输出,当到达记录的两组难度值时,进行以下处理,将前一个难度值的2个任务序号排序,现在既有2组,然后后一个难度值的任务序号,只要在第三组改变一下顺序,就总共有3组输出。
时间复杂度O(n),空间复杂度O(1)。

AC 代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. using namespace std;
  5. typedef struct task
  6. {
  7. int pa[2016];
  8. int num;
  9. }diff;
  10. diff a[2016];
  11. int h3,h1,h2;
  12. int main()
  13. {
  14. int n;
  15. int i,j;
  16. int temp;
  17. int len;
  18. int flag1,flag2;
  19. int cnt;
  20. int order,zu;
  21. while(scanf("%d",&n) != EOF)
  22. {
  23. for(i = 1;i <= 2000;i++)
  24. {
  25. a[i].num = 0;
  26. }
  27. for(i = 1;i <= n;i++)
  28. {
  29. scanf("%d",&temp);
  30. len = a[temp].num;
  31. a[temp].pa[len] = i;
  32. a[temp].num++;
  33. }
  34. flag1 = 0,flag2 = 0;
  35. cnt = 0;
  36. h1 = 0,h2 = 0;
  37. for(i = 1;i <= 2000;i++)
  38. {
  39. if(a[i].num >= 3)
  40. {
  41. flag1 = 1;
  42. h3 = i;
  43. break;
  44. }
  45. if(a[i].num == 2 && h1 == 0)
  46. {
  47. cnt++;
  48. h1 = i;
  49. }
  50. else if(a[i].num == 2 && h2 == 0)
  51. {
  52. cnt++;
  53. h2 = i;
  54. }
  55. if(cnt == 2)
  56. {
  57. flag2 = 1;
  58. break;
  59. }
  60. }
  61. order = 0,zu = 0;
  62. if(flag1)
  63. {
  64. printf("YES\n");
  65. while(zu <= 2)
  66. {
  67. order = 0;
  68. for(i = 1; i <= 2000; i++)
  69. {
  70. if(i == h3)
  71. {
  72. if(order == 0)
  73. {
  74. if(zu == 0)
  75. {
  76. printf("%d %d %d",a[i].pa[0],a[i].pa[1],a[i].pa[2]);
  77. }
  78. if(zu == 1)
  79. {
  80. printf("%d %d %d",a[i].pa[1],a[i].pa[0],a[i].pa[2]);
  81. }
  82. if(zu == 2)
  83. {
  84. printf("%d %d %d",a[i].pa[0],a[i].pa[2],a[i].pa[1]);
  85. }
  86. order += 3;
  87. for(j = 3; j < a[i].num; j++)
  88. {
  89. printf(" %d",a[i].pa[j]);
  90. order++;
  91. }
  92. }
  93. else
  94. {
  95. if(zu == 0)
  96. {
  97. printf(" %d %d %d",a[i].pa[0],a[i].pa[1],a[i].pa[2]);
  98. }
  99. if(zu == 1)
  100. {
  101. printf(" %d %d %d",a[i].pa[1],a[i].pa[0],a[i].pa[2]);
  102. }
  103. if(zu == 2)
  104. {
  105. printf(" %d %d %d",a[i].pa[0],a[i].pa[2],a[i].pa[1]);
  106. }
  107. order += 3;
  108. for(j = 3; j < a[i].num; j++)
  109. {
  110. printf(" %d",a[i].pa[j]);
  111. order++;
  112. }
  113. }
  114. }
  115. else
  116. {
  117. for(j = 0; j < a[i].num; j++)
  118. {
  119. if(order == 0)
  120. {
  121. printf("%d",a[i].pa[j]);
  122. order++;
  123. }
  124. else
  125. {
  126. printf(" %d",a[i].pa[j]);
  127. order++;
  128. }
  129. }
  130. }
  131. }
  132. zu++;
  133. printf("\n");
  134. }
  135. }
  136. else if(flag2)
  137. {
  138. printf("YES\n");
  139. while(zu <= 2)
  140. {
  141. order = 0;
  142. for(i = 1; i <= 2000; i++)
  143. {
  144. if(i == h1)
  145. {
  146. if(order == 0)
  147. {
  148. if(zu == 0) printf("%d %d",a[i].pa[0],a[i].pa[1]);
  149. if(zu == 1) printf("%d %d",a[i].pa[0],a[i].pa[1]);
  150. if(zu == 2) printf("%d %d",a[i].pa[1],a[i].pa[0]);
  151. order += 2;
  152. }
  153. else
  154. {
  155. if(zu == 0) printf(" %d %d",a[i].pa[0],a[i].pa[1]);
  156. if(zu == 1) printf(" %d %d",a[i].pa[0],a[i].pa[1]);
  157. if(zu == 2) printf(" %d %d",a[i].pa[1],a[i].pa[0]);
  158. order += 2;
  159. }
  160. }
  161. else if(i == h2)
  162. {
  163. if(order == 0)
  164. {
  165. if(zu == 0) printf("%d %d",a[i].pa[0],a[i].pa[1]);
  166. if(zu == 1) printf("%d %d",a[i].pa[1],a[i].pa[0]);
  167. if(zu == 2) printf("%d %d",a[i].pa[1],a[i].pa[0]);
  168. order += 2;
  169. }
  170. else
  171. {
  172. if(zu == 0) printf(" %d %d",a[i].pa[0],a[i].pa[1]);
  173. if(zu == 1) printf(" %d %d",a[i].pa[1],a[i].pa[0]);
  174. if(zu == 2) printf(" %d %d",a[i].pa[1],a[i].pa[0]);
  175. order += 2;
  176. }
  177. }
  178. else
  179. {
  180. for(j = 0;j < a[i].num;j++)
  181. {
  182. if(order == 0)
  183. {
  184. printf("%d",a[i].pa[j]);
  185. order++;
  186. }
  187. else
  188. {
  189. printf(" %d",a[i].pa[j]);
  190. order++;
  191. }
  192. }
  193. }
  194. }
  195. zu++;
  196. printf("\n");
  197. }
  198. }
  199. else printf("NO\n");
  200. }
  201. return 0;
  202. }

[题目][I]

George and Accommodation

题目大意:
给出n(1<=n<=100)个房间的已住人数pi和房间容量qi(0<=pi<=qi<=100),求qi-pi>=2个i的个数。

解题思路:
读入pi和qi,然后判断两者差值,若大于或等于2则结果加1.
时间复杂度O(n),空间复杂度O(1)。

AC 代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. using namespace std;
  5. int main()
  6. {
  7. int n;
  8. int ans = 0;
  9. int p,q;
  10. scanf("%d",&n);
  11. while(n--)
  12. {
  13. scanf("%d%d",&p,&q);
  14. if(q-p >= 2) ans++;
  15. }
  16. printf("%d\n",ans);
  17. return 0;
  18. }

[题目][J]

Fedor and New Game

题目大意:
有n个soldiers编号从0到n-1,m+1个player,编号从1到m+1.对于第m+1个player前的每个player的army数值xi进行判断,如果army的表达数xi与第m+1个player的二进制表达中"1"不同的地方不超过k那么第m+1个player的朋友数加1.(1<=k<=n<=20,1<=m<=1000,1<=xi<=2^n-1)

解题思路:
对前m个数的二进制"1"的位置与最后一个数的二进制"1"的位置进行判断,若位置不同数不超过k,则结果加1.把m+1个数转成二进制,然后把每一位数值保存在数组中,并且将数组中第一位拿来保存该数值转成二进制数后的位数。然后分别对前m个二进制位与最后一个数的二进制位进行比较,统计不同位的个数。
时间复杂度O(n),空间复杂度O(1)。

AC 代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. using namespace std;
  5. int n,m,k;
  6. int a[1010][30];
  7. int main()
  8. {
  9. int i,j;
  10. int temp;
  11. int ans = 0;
  12. int cnt = 0;
  13. scanf("%d%d%d",&n,&m,&k);
  14. for(i = 0; i < m+1; i++)
  15. {
  16. scanf("%d",&temp);
  17. j = 1;
  18. while(temp != 0)
  19. {
  20. a[i][j] = temp % 2;
  21. temp = temp / 2;
  22. j++;
  23. }
  24. a[i][0] = j;
  25. }
  26. for(i = 0;i < m;i++)
  27. {
  28. cnt = 0;
  29. for(j = 1;j <= a[i][0] && j <= a[m][0];j++)
  30. {
  31. if(a[i][j] != a[m][j]) cnt++;
  32. }
  33. if(j <= a[i][0])
  34. {
  35. for(;j <= a[i][0];j++)
  36. {
  37. if(a[i][j] == 1) cnt++;
  38. }
  39. }
  40. else
  41. {
  42. for(;j <= a[m][0];j++)
  43. {
  44. if(a[m][j] == 1) cnt++;
  45. }
  46. }
  47. if(cnt <= k) ans++;
  48. }
  49. printf("%d\n",ans);
  50. return 0;
  51. }

[题目][M]

Cheap Travel

题目大意:
进行n次乘车,每次花a元,或者可以选择用b元一次性买好m次乘车的票。(1<=n,m,a,b<=1000),求出要乘n次车最少花的钱。

解题思路:
判断b元m次车票的单价,与a进行比较,选择叫便宜的方式。如果m次车票更好,那么买n/m张m次车票,然后再看剩下的车票用a元票买便宜还是m次车票便宜。
时间复杂度O(1),空间复杂度O(1)。

AC 代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. using namespace std;
  5. int main()
  6. {
  7. int n,m,a,b;
  8. int num;
  9. double x;
  10. int sum = 0;
  11. scanf("%d%d%d%d",&n,&m,&a,&b);
  12. x = (double)b/m;
  13. if(x < (double)a)
  14. {
  15. num = n / m;
  16. sum = num * b;
  17. sum += min(b,a*(n % m));
  18. }
  19. else sum = n*a;
  20. printf("%d\n",sum);
  21. return 0;
  22. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注