补补紫书
第3章
例题部分
例题3-1 TEX Quotes UVa272
简单的输入输出
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| #include <iostream> #include <cstring> #include <cstdio> using namespace std; int main(){ int flag = false; char c; while( (c=getchar()) !=EOF){ if(c == '"'){ if(!flag){ printf("``"); flag = true; } else{ printf("''"); flag = false; } }else printf("%c", c); } return 0; }
|
擅用数组
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #include <iostream> #include <cstring> #include <cstdio> using namespace std; const int maxn = 110; char save[maxn] = "`1234567890-=QWERTYUIOP[]\\ASDFGHJKL;'ZXCVBNM,./\0"; int main(){ char c; int len = sizeof(save); int i; while((c=getchar())!=EOF){ for(i=0; i<len&&save[i]!=c; i++); printf("%c", i==len?c:save[i-1]); } return 0; }
|
例题3-3 Palindromes UVa401
回文与镜像操作
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| #include <iostream> #include <cstring> #include <cstdio> using namespace std; char rev_ch[] = "A 3 HIL JM O 2TUVWXY5"; char rev_in[] = "01SE Z 8 "; const int maxn = 1010; char save[maxn]; int main(){ while(~scanf("%s", save)){ int len = strlen(save); int half = (len-1)/2; bool pali = true, mirr = true; for(int i=0; i<=half; i++){ if(save[i]!=save[len-1-i]) pali = false; if('A'<=save[i]&&save[i]<='Z'){ if(save[len-i-1] != rev_ch[save[i]-'A']) mirr = false; }else{ if(save[len-i-1] != rev_in[save[i]-'0']) mirr = false; } } if(pali){ if(mirr){ printf("%s -- is a mirrored palindrome.", save); }else{ printf("%s -- is a regular palindrome.", save); } }else{ if(mirr){ printf("%s -- is a mirrored string.", save); }else{ printf("%s -- is not a palindrome.", save); } } printf("\n\n"); } return 0; }
|
例题3-4 Master-Mind Hints UVa340
普通计数
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| #include <iostream> #include <cstring> #include <cstdio> using namespace std; const int maxn = 1010; int save[maxn]; int in[maxn]; int num[20]; int num_cp[20]; int main(){ int n, T=0; while(~scanf("%d", &n)){ if(n==0) break; ++T; printf("Game %d:\n", T); for(int i=0; i<10; i++) num[i] = 0; for(int i=0; i<n; i++){ scanf("%d", &save[i]); ++num[save[i]]; } while(1){ memcpy(num_cp, num, sizeof(num)); bool end = true; int match=0, misMatch=0; for(int i=0; i<n; i++){ scanf("%d", &in[i]); if(in[i] != 0) end = false; if(in[i]==save[i]){ ++match; --num_cp[in[i]]; } } for(int i=0; i<n; i++){ if(in[i]!=save[i]) if(num_cp[in[i]]){ ++misMatch; --num_cp[in[i]]; } }
if(end) break; printf(" (%d, %d)\n", match, misMatch); } } return 0; }
|
例题3-5 Digit Generator UVa1583
打表
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| #include <iostream> #include <cstring> #include <cstdio> using namespace std; const int maxn = 100050; int save[maxn]; int gen(int x){ int ans = x; while(x){ ans += x%10; x /= 10; } return ans; } int main(){ memset(save, 0, sizeof(save)); for(int i=1; i<=100000; i++){ int ge = gen(i); if(save[ge]==0) save[ge] = i; } int N; while(~scanf("%d", &N)){ int now; for(int i=0; i<N; i++){ scanf("%d", &now); printf("%d\n", save[now]); } }
return 0; }
|
例题3-6 Circular Sequence UVa1584
环状数组
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| #include <iostream> #include <cstring> #include <cstdio> using namespace std; const int maxn = 110; char str[maxn]; bool compare(int s1, int s2, int len){ int p1 = s1, p2 = s2, p = 0; while(p<len){ ++p; if(str[p1%len] < str[p2%len]) return true; else if(str[p1%len] > str[p2%len]) return false; else{ ++p1; ++p2; } } return true; } int main(){ int T; scanf("%d", &T); while(T--){ scanf("%s", str); int len = strlen(str); int p = 0, ans = 0; while(p<len){ if(compare(p, ans, len)) ans = p; ++p; } p = ans; for(int i=0; i<len; i++){ printf("%c", str[p%len]); ++p; } printf("\n"); } return 0; }
|
习题部分
普通计数
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #include <iostream> #include <cstring> #include <cstdio> using namespace std; const int maxn = 100; char str[maxn]; int main(){ int T; scanf("%d", &T); while(T--){ scanf("%s", str); int ans = 0, combo = 0; int len = strlen(str); for(int i=0; i<len; i++){ if(str[i]=='O'){ combo++; ans += combo; if(str[i+1] != 'O'){ combo = 0; } } } ans += combo; printf("%d\n", ans); } return 0; }
|
简单字符串数字切割
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| #include <iostream> #include <cstring> #include <cstdio> using namespace std; const int maxn = 110; char str[maxn]; double getVal(char tp, int num){ if(tp=='C') return num*12.01; else if(tp=='H') return num*1.008; else if(tp=='O') return num*16.00; else return num*14.01; } int str2int(int s, int e){ int sum = 0, p = s; while(p<=e){ sum *= 10; sum += str[p]-'0'; ++p; } return sum; }
int main(){ int T; scanf("%d", &T); while(T--){ double ans = 0.0f; int num = 0; scanf("%s", str); int p = 0, val = 0, len = strlen(str); char tp; bool counting = false; for(int i=0; i<len; i++){ if('A'<=str[i]&&str[i]<='Z'){ p = i+1; tp = str[i]; if('0'>str[i+1]||str[i+1]>'9'){ ans += getVal(tp, 1); } }else{ if(str[i+1]<'0'||str[i+1]>'9'){ val = str2int(p, i); ans += getVal(tp, val); } } }
printf("%.3lf\n", ans);
} return 0; }
|
习题3-3 Digit Counting UVa1225
普通地打了个表
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| #include <iostream> #include <cstring> #include <cstdio> using namespace std; const int maxn = 10010; int res[maxn][10]; void update(int num){ int index = num; while(num){ ++res[index][num%10]; num /= 10; } } int main(){ int T; scanf("%d", &T); memset(res, 0, sizeof(res)); for(int i=1; i<=10000; i++){ memcpy(res[i], res[i-1], 10*sizeof(int)); update(i); } while(T--){ int n; scanf("%d", &n); for(int i=0; i<=9; i++){ printf("%d%c", res[n][i], i==9?'\n':' '); } } return 0; }
|
习题3-4 Periodic Strings UVa455
最小周期串
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| #include <iostream> #include <cstring> #include <cstdio> using namespace std; const int maxn = 100; char str[maxn]; int main(){ int n; scanf("%d", &n); while(n--){ scanf("%s", str); int len = strlen(str), res = 1; while(res<=len){ if(len%res) { ++res; continue; } int rep = len/res; --rep; bool flag = true; while(rep){ for(int i=0+res*rep, p=0; p<res; i++,p++){ if(str[p] != str[i]){ flag = false; break; } } --rep; if(!flag) break; } if(flag) break; ++res; } printf("%d\n", res); if(n!=0) printf("\n"); } return 0; }
|
习题3-5 Puzzle UVa227
输入输出有点卡人… 学会了使用fgets..以前都在使用危险的gets
我每次switch都忘记写break呢
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
| #include <iostream> #include <cstring> #include <cstdio> using namespace std; const int maxn = 10; char puzz[maxn][maxn]; int main(){ int sx, sy; int rnd = 1; bool first = true; while(fgets(puzz[0], maxn, stdin) != NULL){ if(strlen(puzz[0])<5 && puzz[0][0]=='Z'){ break; } if(first) first = false; else printf("\n"); for(int i=1; i<5; i++){ fgets(puzz[i], maxn, stdin); } for(int i=0; i<5; i++) for(int j=0; j<5; j++){ if(puzz[i][j] == ' '){ sx = i; sy = j; } }
char op[110]; bool flag = true; while(~scanf("%s", op)){ getchar(); int len = strlen(op); bool bre = false; for(int i=0; i<len; i++){ switch(op[i]){ case 'A': if(0<=sx-1){ swap(puzz[sx][sy], puzz[sx-1][sy]); sx -= 1; }else flag = false; break; case 'B': if(5>sx+1){ swap(puzz[sx][sy], puzz[sx+1][sy]); sx += 1; }else flag = false; break; case 'L': if(0<=sy-1){ swap(puzz[sx][sy], puzz[sx][sy-1]); sy -= 1; }else flag = false; break; case 'R': if(5>sy+1){ swap(puzz[sx][sy], puzz[sx][sy+1]); sy += 1; }else flag = false; break; default: if(op[i]!='0') flag = false; else bre = true; } } if(bre) break; } printf("Puzzle #%d:\n", rnd++); if(!flag){ printf("This puzzle has no final configuration.\n"); }else{ for(int i=0; i<5; i++){ for(int j=0; j<5; j++){ printf("%c%c", puzz[i][j], j==4?'\n':' '); } } } } return 0; }
|
习题3-6 Crossword Answers UVa232
嗯…无感想
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| #include <iostream> #include <cstring> #include <cstdio> #include <vector> using namespace std; const int maxn = 15; char puzz[maxn][maxn]; bool used[maxn][maxn]; vector<pair<int,int> > strBlock; void add(int x, int y, int &num){ strBlock.push_back(make_pair(x, y)); } void print(int i){ if(i+1<10) printf(" %d.", i+1); else if(10<=i+1&&i+1<100) printf(" %d.", i+1); else printf("%d.", i+1); } int main(){ int r, c; int rnd = 1; bool first = true; while(~scanf("%d", &r)){ if(!r) break; if(first) first = 0; else printf("\n"); strBlock.clear(); scanf("%d", &c); int num = 0; for(int i=0; i<r; i++){ scanf("%s", puzz[i]); for(int j=0; j<c; j++){ if(puzz[i][j]!='*'){ if(j-1<0 || i-1<0) { add(i, j, num); }else if(0<=j-1&&puzz[i][j-1]=='*'){ add(i, j, num); }else if(0<=i-1&&puzz[i-1][j]=='*'){ add(i, j, num); } } } } int len = strBlock.size(); memset(used, 0, sizeof(used)); printf("puzzle #%d:\nAcross\n", rnd++); for(int i=0; i<len; i++){ int px = strBlock[i].first; int py = strBlock[i].second; if(used[px][py]) continue; print(i); while(py<c && puzz[px][py]!='*'){ used[px][py] = true; printf("%c", puzz[px][py]); ++py; } printf("\n"); } printf("Down\n"); memset(used, 0, sizeof(used)); for(int i=0; i<len; i++){ int px = strBlock[i].first; int py = strBlock[i].second; if(used[px][py]) continue; print(i); while(px<r && puzz[px][py]!='*'){ used[px][py] = true; printf("%c", puzz[px][py]); ++px; } printf("\n"); } } return 0; }
|
习题3-7 DNA Consensus String UVa1368
记个数
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| #include <iostream> #include <cstring> #include <cstdio> #include <vector> using namespace std; char str[60][1010]; int main(){ int T; scanf("%d", &T); while(T--){ int m, n; scanf("%d%d", &m, &n); for(int i=0; i<m; i++){ scanf("%s", str[i]); } int ans = 0; for(int j=0; j<n; j++){ int sum[4]; memset(sum, 0, sizeof(sum)); for(int i=0; i<m; i++){ switch(str[i][j]){ case 'A': ++sum[0]; break; case 'C': ++sum[1]; break; case 'G': ++sum[2]; break; case 'T': ++sum[3]; break; default: break; } } if(sum[0]>=sum[1] && sum[0]>=sum[2] && sum[0]>=sum[3]){ printf("A"); ans += sum[1]+sum[2]+sum[3]; }else if(sum[1]>=sum[0] && sum[1]>=sum[2] && sum[1]>=sum[3]){ printf("C"); ans += sum[0]+sum[2]+sum[3]; }else if(sum[2]>=sum[0] && sum[2]>=sum[1] && sum[2]>=sum[3]){ printf("G"); ans += sum[0]+sum[1]+sum[3]; }else{ printf("T"); ans += sum[0]+sum[1]+sum[2]; } } printf("\n%d\n", ans); } return 0; }
|
习题3-8 Repeating Decimals UVa202
手写大数除法的基础?
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| #include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <cmath> using namespace std; const int maxn = 3010; int used[maxn]; int ans[100010]; int main(){ int a, b, c; while(~scanf("%d%d", &a, &b)){ memset(used, 0, sizeof(used)); c = a/b; printf("%d/%d = %d.", a, b, c); int rep = 0, sta = 1; a -= c*b; while(a%b){ if(used[a]) { sta = used[a]; break; }else used[a] = rep+1; a *= 10; c = a/b; ans[++rep] = c; a -= c*b; } bool div = false; if(rep<=50){ if(a%b==0){ div = true; for(int i=1; i<=rep; i++) printf("%d", ans[i]); printf("(0)\n"); }else{ for(int i=1; i<sta; i++) printf("%d", ans[i]); printf("("); for(int i=sta; i<=rep; i++) printf("%d", ans[i]); printf(")\n"); } }else{ if(a%b==0){ div = true; for(int i=1; i<=50; i++) printf("%d", ans[i]); printf("...\n"); }else{ for(int i=1; i<sta; i++) printf("%d", ans[i]); printf("("); for(int i=sta; i<=50; i++) printf("%d", ans[i]); printf("...)\n"); } } printf(" %d = number of digits in repeating cycle\n\n", div?1:rep+1-sta); } return 0; }
|
习题3-9 All in All UVa10340
初看以为是最大公共子串, 但其实只要遍历母串时看看子串是否匹配就好惹
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <cmath> using namespace std; const int maxn = 100010; char str[maxn], pat[maxn]; int main(){ while(~scanf("%s%s", pat, str)){ int lens = strlen(str), lenp = strlen(pat); int p = 0; for(int i=0; i<lens; i++){ if(p<lenp && str[i] == pat[p]) ++p; } if(p==lenp) printf("Yes\n"); else printf("No\n"); } return 0; }
|
先把六个面排序, 筛选出三个面来, 如果能组成长方体的话这三个面的边长有逻辑关系, 写个判断
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| #include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <cmath> #include <algorithm> using namespace std; const int maxn =1010; pair<int, int> cov[10]; bool vis[maxn]; bool can(pair<int, int> a, pair<int, int> b, pair<int, int> c){ if(a.first==b.first){ if(a.second == c. first){ if(c.second == b.second) return true; }else if(a.second == c.second){ if(c.first == b.second) return true; } } return false; } int main(){ while(~scanf("%d%d", &cov[0].first, &cov[0].second)){ memset(vis, 0, sizeof(vis)); for(int i=1; i<6; i++){ scanf("%d%d", &cov[i].first, &cov[i].second); } for(int i=0; i<6; i++){ if(cov[i].first > cov[i].second) swap(cov[i].first, cov[i].second); } sort(cov, cov+6); bool flag = true; for(int i=0; i<6; i+=2){ if(cov[i]!=cov[i+1]) flag = false; } if(!can(cov[0], cov[2], cov[4])) flag = false; if(flag) printf("POSSIBLE\n"); else printf("IMPOSSIBLE\n"); } return 0; }
|
习题3-11 Kickdown UVa1588
wa了很久…玉山啊..边界条件不考虑清楚就写….
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| #include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <cmath> #include <algorithm> using namespace std; const int maxn = 1010; char s1[maxn], s2[maxn]; int main(){ while(~scanf("%s%s", s1, s2)){ int len1 = strlen(s1), len2 = strlen(s2); if(len1>len2){ swap(s1, s2); swap(len1, len2); } int ans = len1+len2; bool flag; for(int i=0; i<len1; i++){ flag = true; for(int j=0; i+j<len1; j++){ if( (s1[i+j]-'0')+(s2[j]-'0') >3){ flag = false; break; } } if(flag){ if(ans > i+len2) { ans = i+len2; } } } for(int i=0; i<len2; i++){ flag = true; for(int j=0; i+j<len2 && j<len1; j++){ if( (s1[j]-'0')+(s2[i+j]-'0')>3 ){ flag = false; break; } } if(flag){ int now = max(i+len1, len2); if(ans > now){ ans = now; } } } printf("%d\n", ans); } return 0; }
|
习题3-12 Floating-Point Numbers UVa11809
这题好玩, 题面复习了一遍浮点数在计算机内是如何存储的.
上图中8-bit用来存储Mantissa(尾数), 6-bit用于存储exponent(阶码).
本题默认首位为0, 即表示的是正数. 图中8-bit Mantissa+6-bit expnent最大能表示的浮点数为$0.11111111_2\times 2^{111111_2}=0.998046875 \times 2^{63}=9.205357638345293824e18$, 我们记为$M_2\times 2^{E_2}=A\times 10^B$
现在以$A\times 10^B$的形式输入计算机能表示的最大浮点数, 求M, E的位数. 直接算很麻烦, 由于题目明确说明$0\le M\le 9, 1\le E\le 30$, 所以我们可以直接打表, 把10*30种情况打出来. 还有一个问题, $2^{E_2}$会非常大,直接算会变成inf. 此处使用一个log操作:
$log(M_2\times 2^{E_2})=log(A\times 10^B)$
$logM_2+ E_2\times log2=logA+ B$
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| #include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <cmath> #include <algorithm> using namespace std; const double logt = log10(2); const double eps = 1e-6; double base[2] = {0.1, 10}; double save[15][35]; double str2dou(char* str, int len){ bool flag = true; double now = 1, ans = 0; for(int i=0; i<len; i++){ if(str[i]=='.'){ flag = false; now = 0.1; }else{ if(flag){ ans*=10; ans += str[i]-'0'; }else{ ans += (str[i]-'0')*now; now *= base[flag]; } } } return ans; }
void init(){ double sum1 = 0; double now1 = 0.5; for(int m=0; m<=9; m++){ sum1 += now1; now1 /= 2; double sum2 = 0; double now2 = 1; for(int e=1; e<=30; e++){ sum2 += now2; now2 *= 2; save[m][e] = log10(sum1) + sum2*logt; } }
} int main(){ char str[110]; init(); while(~scanf("%s", str)){ int pos_e; int len = strlen(str); for(pos_e=0; str[pos_e]!='e'; pos_e++); str[pos_e] = '\0'; char* A = str; char* B = str+pos_e+1; int lenA = strlen(A), lenB = strlen(B); if(lenA==1 && lenB==1 && A[0]=='0' && B[0]=='0') break; double a = str2dou(A, lenA), b = str2dou(B, lenB); bool found = false; for(int m=0; m<=9; m++){ for(int e=1; e<=30; e++){ if(abs(log10(a)+b - save[m][e])<eps){ found = true; printf("%d %d\n", m, e); break; } } if(found) break; } } return 0; }
|
第4章
例题部分
例题4-1 Ancient Cipher UVa1339
时隔一年的排序
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| #include <stdio.h> #include <cstring> #include <iostream> #include <cmath> #include <algorithm> using namespace std; const int maxn = 110; int main(){ char a[maxn], b[maxn]; int staa[26], stab[26]; while(~scanf("%s%s", a, b)){ memset(staa, 0, sizeof(staa)); memset(stab, 0, sizeof(stab)); int len = strlen(a); for(int i=0; i<len; i++){ staa[a[i]-'A']++; stab[b[i]-'A']++; } sort(staa, staa+26); sort(stab, stab+26); bool flag = true; for(int i=0; i<26; i++){ if(staa[i]!=stab[i]){ flag = false; break; } } if(flag) printf("YES\n"); else printf("NO\n"); } return 0; }
|
习题4-2 Hangman Judge UVa489
习题部分