@xingxing
2016-12-08T14:49:49.000000Z
字数 7574
阅读 1066
题解
[题目][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代码:
#include <iostream>#include <cstdio>#include <cstdlib>#include <cmath>using namespace std;int solve(int m){int i;for(i = 2;i <= (int)sqrt(m);i++){if(m % i == 0){return 1;}}return 0;}int main(){int n;int i;while(scanf("%d",&n) != EOF){for(i = n/2;i > 1;i--){if(solve(i) && solve(n-i)){printf("%d %d\n",i,n-i);break;}}}return 0;}
[题目][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代码:
#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>using namespace std;int f[2016];int main(){int n,k;int i;int ans;while(scanf("%d %d",&n,&k) != EOF){ans = 0;for(i = 0;i < n;i++){scanf("%d",&f[i]);}sort(f,f+n);if(n >= k){for(i = n-1; i >= 0 && i+1 >= k;i -= k){ans += 2*(f[i] - 1);}if(i+1 < k && i >= 0){ans += (f[i]-1)*2;}}else{ans += 2*(f[n-1]-1);}printf("%d\n",ans);}return 0;}
[题目][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代码:
#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>using namespace std;const int maxx = 123456;typedef struct name{char f[60],s[60];int flag;}person;person a[maxx];int main(){//freopen("in.txt","r",stdin);int n;int i;int num;char temp[60];int flag1 = 0;scanf("%d",&n);for(i = 0;i < n;i++){getchar();scanf("%s",a[i].f);getchar();scanf("%s",a[i].s);if(strcmp(a[i].f,a[i].s) >= 0) a[i].flag = 1;else a[i].flag = 0;}for(i = 0;i < n;i++){scanf("%d",&num);if(i == 0 && a[num-1].flag == 1){strcpy(temp,a[num-1].s);}else if(i == 0 && a[num-1].flag == 0)strcpy(temp,a[num-1].f);if(i != 0){if(a[num-1].flag == 1){if(strcmp(temp,a[num-1].f) >= 0)flag1 = 1;else{if(strcmp(temp,a[num-1].s) >= 0)strcpy(temp,a[num-1].f);else strcpy(temp,a[num-1].s);}}else{if(strcmp(temp,a[num-1].s) >= 0) flag1 = 1;else{if(strcmp(temp,a[num-1].f) >= 0)strcpy(temp,a[num-1].s);else strcpy(temp,a[num-1].f);}}}}if(flag1 == 1) printf("NO\n");else printf("YES\n");return 0;}
[题目][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代码:
#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>using namespace std;int a[20];int main(){int i;int len;int flag1,flag2;flag1 = 0,flag2 = 0;for(i = 0;i < 6;i++){scanf("%d",&len);a[len]++;}for(i = 1; i <= 9; i++){if(a[i] == 4){flag1 = 1;}if(a[i] == 2){flag2 = 1;}if(a[i] == 6){flag1 = 1;flag2 = 1;}if(a[i] == 5){flag1 = 1;flag2 = 0;}}if(flag1 && flag2)printf("Elephant\n");else if(flag1 && flag2 == 0)printf("Bear\n");else printf("Alien\n");return 0;}
[题目][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 代码:
#include <iostream>#include <cstdio>#include <cstdlib>using namespace std;typedef struct task{int pa[2016];int num;}diff;diff a[2016];int h3,h1,h2;int main(){int n;int i,j;int temp;int len;int flag1,flag2;int cnt;int order,zu;while(scanf("%d",&n) != EOF){for(i = 1;i <= 2000;i++){a[i].num = 0;}for(i = 1;i <= n;i++){scanf("%d",&temp);len = a[temp].num;a[temp].pa[len] = i;a[temp].num++;}flag1 = 0,flag2 = 0;cnt = 0;h1 = 0,h2 = 0;for(i = 1;i <= 2000;i++){if(a[i].num >= 3){flag1 = 1;h3 = i;break;}if(a[i].num == 2 && h1 == 0){cnt++;h1 = i;}else if(a[i].num == 2 && h2 == 0){cnt++;h2 = i;}if(cnt == 2){flag2 = 1;break;}}order = 0,zu = 0;if(flag1){printf("YES\n");while(zu <= 2){order = 0;for(i = 1; i <= 2000; i++){if(i == h3){if(order == 0){if(zu == 0){printf("%d %d %d",a[i].pa[0],a[i].pa[1],a[i].pa[2]);}if(zu == 1){printf("%d %d %d",a[i].pa[1],a[i].pa[0],a[i].pa[2]);}if(zu == 2){printf("%d %d %d",a[i].pa[0],a[i].pa[2],a[i].pa[1]);}order += 3;for(j = 3; j < a[i].num; j++){printf(" %d",a[i].pa[j]);order++;}}else{if(zu == 0){printf(" %d %d %d",a[i].pa[0],a[i].pa[1],a[i].pa[2]);}if(zu == 1){printf(" %d %d %d",a[i].pa[1],a[i].pa[0],a[i].pa[2]);}if(zu == 2){printf(" %d %d %d",a[i].pa[0],a[i].pa[2],a[i].pa[1]);}order += 3;for(j = 3; j < a[i].num; j++){printf(" %d",a[i].pa[j]);order++;}}}else{for(j = 0; j < a[i].num; j++){if(order == 0){printf("%d",a[i].pa[j]);order++;}else{printf(" %d",a[i].pa[j]);order++;}}}}zu++;printf("\n");}}else if(flag2){printf("YES\n");while(zu <= 2){order = 0;for(i = 1; i <= 2000; i++){if(i == h1){if(order == 0){if(zu == 0) printf("%d %d",a[i].pa[0],a[i].pa[1]);if(zu == 1) printf("%d %d",a[i].pa[0],a[i].pa[1]);if(zu == 2) printf("%d %d",a[i].pa[1],a[i].pa[0]);order += 2;}else{if(zu == 0) printf(" %d %d",a[i].pa[0],a[i].pa[1]);if(zu == 1) printf(" %d %d",a[i].pa[0],a[i].pa[1]);if(zu == 2) printf(" %d %d",a[i].pa[1],a[i].pa[0]);order += 2;}}else if(i == h2){if(order == 0){if(zu == 0) printf("%d %d",a[i].pa[0],a[i].pa[1]);if(zu == 1) printf("%d %d",a[i].pa[1],a[i].pa[0]);if(zu == 2) printf("%d %d",a[i].pa[1],a[i].pa[0]);order += 2;}else{if(zu == 0) printf(" %d %d",a[i].pa[0],a[i].pa[1]);if(zu == 1) printf(" %d %d",a[i].pa[1],a[i].pa[0]);if(zu == 2) printf(" %d %d",a[i].pa[1],a[i].pa[0]);order += 2;}}else{for(j = 0;j < a[i].num;j++){if(order == 0){printf("%d",a[i].pa[j]);order++;}else{printf(" %d",a[i].pa[j]);order++;}}}}zu++;printf("\n");}}else printf("NO\n");}return 0;}
[题目][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 代码:
#include <iostream>#include <cstdio>#include <cstdlib>using namespace std;int main(){int n;int ans = 0;int p,q;scanf("%d",&n);while(n--){scanf("%d%d",&p,&q);if(q-p >= 2) ans++;}printf("%d\n",ans);return 0;}
[题目][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 代码:
#include <iostream>#include <cstdio>#include <cstdlib>using namespace std;int n,m,k;int a[1010][30];int main(){int i,j;int temp;int ans = 0;int cnt = 0;scanf("%d%d%d",&n,&m,&k);for(i = 0; i < m+1; i++){scanf("%d",&temp);j = 1;while(temp != 0){a[i][j] = temp % 2;temp = temp / 2;j++;}a[i][0] = j;}for(i = 0;i < m;i++){cnt = 0;for(j = 1;j <= a[i][0] && j <= a[m][0];j++){if(a[i][j] != a[m][j]) cnt++;}if(j <= a[i][0]){for(;j <= a[i][0];j++){if(a[i][j] == 1) cnt++;}}else{for(;j <= a[m][0];j++){if(a[m][j] == 1) cnt++;}}if(cnt <= k) ans++;}printf("%d\n",ans);return 0;}
[题目][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 代码:
#include <iostream>#include <cstdio>#include <cstdlib>using namespace std;int main(){int n,m,a,b;int num;double x;int sum = 0;scanf("%d%d%d%d",&n,&m,&a,&b);x = (double)b/m;if(x < (double)a){num = n / m;sum = num * b;sum += min(b,a*(n % m));}else sum = n*a;printf("%d\n",sum);return 0;}