1 Your Ride Is Here
将给出的名字(长度1-6)中的A-Z映射为1-26,判断给出的两个名字对应的字母乘积模47是否相同,是输出“GO”,否则输出“STAY”。
#include <stdio.h> int main (int argc, char* argv[]) { FILE *fin = fopen ("ride.in", "r"); FILE *fout = fopen ("ride.out", "w"); int comet, group, i; char cn[8], gn[8], *ptr; fscanf (fin, "%s", cn); fscanf (fin, "%s", gn); for (comet = 1, ptr = cn; *ptr; ++ptr) comet *= *ptr -'A'+1; for (group = 1, ptr = gn; *ptr; ++ptr) group *= *ptr -'A'+1; fprintf (fout, "%s\n", (comet%47 == group%47) ? "GO" : "STAY"); exit (0); }
2 Greedy Gift Givers
给出每个人的名字以及对应的礼品金额、朋友数和朋友的名字,算出每个人最后的盈亏。(NP问题?2<= NP <=10)
下面解法复杂度为O(n^3),利用哈希表可以降为O(n^2)
#include <stdio.h> #include <stdlib.h> long hash(char *s){ long code = *s-'a'; while (*++s) code = code*10 + *s-'a'; return code; } typedef struct{ char name[20]; long hashcode; int amount; } Person; int main (int argc, char *argv[]) { FILE *fin = fopen ("gift1.in", "r"); FILE *fout = fopen ("gift1.out", "w"); int n, i, average, amount, friends; char name[20]; long hashcode; Person *people, *who, *whom; fscanf(fin, "%d", &n); people = (Person*)malloc(sizeof(Person)*n); for (i = 0; i < n; ++i){ fscanf(fin, "%s", people[i].name); people[i].hashcode = hash(people[i].name); people[i].amount = 0; } for (i = 0; i < n; ++i){ fscanf(fin, "%s", name); fscanf(fin, "%d %d", &amount, &friends); for (hashcode = hash(name), who = people; who->hashcode != hashcode; ++who); if (amount && friends){ average = amount/friends; who->amount -= average*friends; while (friends--){ fscanf(fin, "%s", name); for (hashcode = hash(name), whom = people; whom->hashcode != hashcode; ++whom); whom->amount += average; }} } for (i = 0; i < n; ++i) fprintf (fout, "%s %d\n", people[i].name, people[i].amount); exit (0); }
3 Friday the Thirteenth
已知1900年1月1日是星期一,给出N(1 <= N <= 400),算出1900年1月1日至1900+N-1年12月31日中13号落在周一到周日的次数。
#include <stdio.h> int leap_year(int year){ return (year%100==0) ? year%400==0 : year%4==0; } int months[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int counts[7]; int main (int argc, char *argv[]) { FILE *fin = fopen ("friday.in", "r"); FILE *fout = fopen ("friday.out", "w"); int n, i, j, at=6; fscanf(fin, "%d", &n); for (i = 0; i < n; ++i){ for (j = 0; j < 12; ++j){ counts[at]++; at = (at + months[j] + (j==1 && leap_year(1900+i)))%7; } } fprintf(fout, "%d %d %d %d %d %d %d\n", counts[6], counts[0], counts[1], counts[2], counts[3], counts[4], counts[5]); exit (0); }
4 Broken Necklace
给出项链的串(如brbrrrbbbrrrrrbrrbbrbbbbrrrrb,对应图A),求出从某个地方断开能收集的珠子的最大长度。
规则:分别向左和向右开始收集同颜色的珠子直到你遇到一个不同的颜色珠子(白色当作红色或绿色)。
1 2 1 2 r b b r b r r b r b b b r r b r r r w r b r w w b b r r b b b b b b r b r r b r b r r r b r r r r r r b r b r r r w Figure A Figure B r red bead b blue bead w white bead
简单的搜索也能AC,复杂度O(n^2),我想了个比较笨的方法,理论上的是O(n)
/* ID: shaojie2 LANG: C TASK: beads */ #include <stdio.h> /* * 因为只需考虑断点在红与蓝之间的情况,所以 * 先将输入处理为一个个{颜色,长度}的节点, * 并假设输入的串里红与蓝中间一定会有白色节点(长度可以为零),就像: * ... [w x1] [r x2] [w x3] [b x4] [w x5] [r x6] ... * w0 pre w1 cur w2 next * 从 x1 到 x5 的五个节点的总长度即是从 x3 分开的长度。 * 每次处理完 next 节点就开始处理前面的五个节点。 * 将原输入两倍化以便消除头尾连接问题。 */ struct { int color; /* Zero is reguarded as WHITE */ int len; } white1, pre, white2, cur, white3, next; char beads[701]; int max_len = 0; int main (int argc, char *argv[]) { FILE *fin = fopen ("beads.in", "r"); FILE *fout = fopen ("beads.out", "w"); int N, i = 0, total = 0; fscanf (fin, "%d", &N); fscanf (fin, "%s", beads); for (i = 0; i < N; ++i) beads[N+i] = beads[i]; beads[N*=2] = '\0'; i = 0; while(i < N){ WHITE_2: white2.len = 0; while (i < N && beads[i] == 'w') ++ white2.len, ++i; if (i == N) break; CUR: cur.color = beads[i]; cur.len = 0; while (i < N && beads[i] == cur.color) ++ cur.len, ++i; if (cur.color == pre.color){ //颜色相同则合并节点 pre.len += cur.len + white2.len; goto WHITE_2; } if (i == N) break; WHITE_3: white3.len = 0; while (i < N && beads[i] == 'w') ++ white3.len, ++i; if (i == N) break; NEXT: next.color = beads[i]; next.len = 0; while (i < N && beads[i] == next.color) ++ next.len, ++i; if (next.color == cur.color){ //颜色相同则合并节点 cur.len += next.len + white3.len; goto WHITE_3; } if (i == N)break; //计算在 pre 和 cur 之间断开能收集的长度 total = white1.len + pre.len + white2.len + cur.len + white3.len; if (total > max_len) max_len = total; else total -= white3.len; //移动节点 white1 = white2; pre = cur; white2 = white3; cur = next; goto WHITE_3; } total = white1.len + pre.len + white2.len + cur.len + white3.len; if (total > max_len) max_len = total; //若最大长度比给定的长度还长,则说明正条项链都可以被收集 fprintf (fout, "%d\n", max_len > N/2 ? N/2 : max_len); exit (0); }