这里会显示出您选择的修订版和当前版本之间的差别。
后一修订版 | 前一修订版 | ||
2020-2021:teams:namespace:sereinin:语言篇 [2020/05/15 21:21] serein 创建 |
— (当前版本) | ||
---|---|---|---|
行 1: | 行 1: | ||
- | //2020-05-05// | ||
- | ====== 第2章 循环结构程序设计 ====== | ||
- | |||
- | ===== 用计时函数测试程序效率 ===== | ||
- | |||
- | <code c> | ||
- | #include <time.h> | ||
- | |||
- | printf("Time used = %.2f\n",(double)clock()/CLOCKS_PER_SEC); | ||
- | </code> | ||
- | ===== 输入输出重定向 ===== | ||
- | |||
- | * 基础版本 | ||
- | |||
- | <code c> | ||
- | freopen("input.txt","r",stdin); | ||
- | freopen("output.txt","w",stdout); | ||
- | </code> | ||
- | * 本地版本 | ||
- | |||
- | <code c> | ||
- | #define LOCAL | ||
- | |||
- | #ifdef LOCAL | ||
- | |||
- | freopen("input.txt","r",stdin); | ||
- | freopen("output.txt","w",stdout); | ||
- | |||
- | #endif | ||
- | </code> | ||
- | * ''%%fopen%%'' 版本 | ||
- | |||
- | <code c> | ||
- | FILE *fin,*fout; | ||
- | fin = fopen("data.in","rb"); | ||
- | fout = fopen("data.out","wb"); | ||
- | //输入 | ||
- | fscanf(fin,"%d",&x); | ||
- | //输出 | ||
- | fprintf(fout,"%d %d %.3f\n",min,max,(double)s/n); | ||
- | //关闭文件 | ||
- | fclose(fin); | ||
- | fclose(fout); | ||
- | </code> | ||
- | ====== 第3章 数组和字符串 ====== | ||
- | |||
- | ===== 数组 ===== | ||
- | |||
- | * 数组赋值函数 ''%%memcpy%%'' | ||
- | |||
- | <code c> | ||
- | #include<string.h> | ||
- | |||
- | memcpy(b,a,sizeof(int)*k);//int型 | ||
- | memcpy(b,a,sizeof(double)*k);//double型 | ||
- | memcpy(b,a,sizeof(a));//全部复制 | ||
- | </code> | ||
- | * 数组清零 | ||
- | |||
- | <code c> | ||
- | #include<string.h> | ||
- | memset(a,0,sizeof(a)); | ||
- | </code> | ||
- | * 蛇形填数(伪代码) | ||
- | |||
- | <code c> | ||
- | #define maxn 20 | ||
- | int a[maxn][maxn],tot; | ||
- | tot = a[x=0][y=n-1] =1; | ||
- | while(tot< n*n) | ||
- | { | ||
- | while(x+1<n && !a[x+1][y]) a[++x][y] = ++tot; | ||
- | while(y-1>=0 && !a[x][y-1]) a[x][--y] = ++tot; | ||
- | while(x-1>=0 && !a[x-1][y]) a[--x][y] = ++tot; | ||
- | while(y+1<n && !a[x][y+1]) a[x][++y] = ++tot; | ||
- | } | ||
- | </code> | ||
- | * 竖式问题 | ||
- | |||
- | <code c> | ||
- | #include<stdio.h> | ||
- | #include<string.h> | ||
- | int main() | ||
- | { | ||
- | int count = 0; | ||
- | char s[20]; buf[99]; | ||
- | scanf("%s",s); | ||
- | for(int abc=111; abc <= 999; abc++) | ||
- | for(int de =11; de <= 99; de++) | ||
- | { | ||
- | int x = abc*(de%10), y = abc*(de/10), z = abc*de; | ||
- | sprintf(buf,"%d%d%d%d%d%d"), abc, de, x, y, z); | ||
- | int ok = 1; | ||
- | for(int i = 0; i <strlen(buf); i++) | ||
- | if(strchr(s, buf[i]) == NULL) ok = 0; | ||
- | if(ok) | ||
- | { | ||
- | printf("<%d>\n", ++count); | ||
- | printf("%5d\nX%4d\n-----\n%5d\n%4d\n-----\n%5d\n\n", abc,de,x,y,z); | ||
- | } | ||
- | } | ||
- | printf("The number of solutions = %d\n", count); | ||
- | return 0; | ||
- | } | ||
- | </code> | ||
- | ===== 竞赛题目选讲 ===== | ||
- | |||
- | * TeX中的引号($UVa272$) | ||
- | |||
- | <code c> | ||
- | #include<stdio.h> | ||
- | int main(){ | ||
- | int c,q=1; | ||
- | while((c=getchar()) != EOF){ | ||
- | if(c = '"') { printf("%s", q ? "``" ; "''"); q = !q; } | ||
- | else printg("%c", c); | ||
- | } | ||
- | return 0; | ||
- | } | ||
- | </code> | ||
- | <HTML><ul></HTML> | ||
- | <HTML><li></HTML><HTML><p></HTML>$WERTYU$($UVa10082$)<HTML></p></HTML> | ||
- | <HTML><p></HTML>善用常量数组往往能简化代码。定义常量数组时无须指明大小,编译器会计算。<HTML></p></HTML><HTML></li></HTML><HTML></ul></HTML> | ||
- | |||
- | <code c> | ||
- | #include<stdio.h> | ||
- | char s[] = "`1234567890-=QWERTYUIOP[]\\ASDFGHJKL;'ZXCVBNM,./"; | ||
- | int main(){ | ||
- | int i, c; | ||
- | while((c = getchar()) != EOF){ | ||
- | for (i=1; s[i] && s[i]!=c;i++); | ||
- | if(s[i]) putchar(s[i-1]); | ||
- | else putchar(c); | ||
- | } | ||
- | return 0; | ||
- | } | ||
- | </code> | ||
- | <HTML><ul></HTML> | ||
- | <HTML><ul></HTML> | ||
- | <HTML><li></HTML><HTML><p></HTML>回文词($UVa401$)<HTML></p></HTML> | ||
- | <HTML><p></HTML>输入一个字符串,判断它是否为回文串以及镜像串。输入字符串保证不含数字0。(使用常量数组)<HTML></p></HTML><HTML></li></HTML><HTML></ul></HTML> | ||
- | |||
- | <code c> | ||
- | #include<stdio.h> | ||
- | #include<string.h> | ||
- | #include<ctype.h> | ||
- | const char* rev = "A 3 HIL JM O 2TUVWXY51SE Z 8 "; | ||
- | const char* msg[] = {"not a palindrome", "a regular palindrome", "a mirrored string", "a mirrored palindrome"}; | ||
- | |||
- | char r(char ch) { | ||
- | if(isalpha(ch)) return rev[ch - 'A']; | ||
- | return rev[ch - '0' + 25]; | ||
- | } | ||
- | |||
- | int main() { | ||
- | char s[30]; | ||
- | while(scanf("%s", s) == 1) { | ||
- | int len = strlen(s); | ||
- | int p = 1, m = 1; | ||
- | for(int i = 0; i < (len+1)/2; i++) { | ||
- | if(s[i] != s[len-1-i]) p = 0; | ||
- | if(r(s[i]) != s[len-1-i]) m = 0; | ||
- | } | ||
- | printf("%s -- is %s.\n\n", s, msg[m*2+p]); | ||
- | } | ||
- | return 0; | ||
- | } | ||
- | </code> | ||
- | <HTML><ul></HTML> | ||
- | <HTML><li></HTML><HTML><p></HTML>猜数字游戏的提示($UVa340$)<HTML></p></HTML> | ||
- | <HTML><p></HTML>直接统计可得A,为了求B,对于每个数字(1~9),统计二者出现次数的最小值之和就是该数字对B的贡献。<HTML></p></HTML> | ||
- | <HTML><p></HTML>最后输出A,B-A即可。<HTML></p></HTML><HTML></li></HTML><HTML></ul></HTML> | ||
- | |||
- | <code c> | ||
- | #include<stdio.h> | ||
- | #define maxn 1000 + 10 | ||
- | |||
- | int main() { | ||
- | int n, a[maxn], b[maxn]; | ||
- | int kase = 0; | ||
- | while(scanf("%d", &n) == 1 && n) { // n=0时输入结束 | ||
- | printf("Game %d:\n", ++kase); | ||
- | for(int i = 0; i < n; i++) scanf("%d", &a[i]); | ||
- | for(;;) { | ||
- | int A = 0, B = 0; | ||
- | for(int i = 0; i < n; i++) { | ||
- | scanf("%d", &b[i]); | ||
- | if(a[i] == b[i]) A++; | ||
- | } | ||
- | if(b[0] == 0) break; // 正常的猜测序列不会有0,所以只判断第一个数是否为0即可 | ||
- | for(int d = 1; d <= 9; d++) { | ||
- | int c1 = 0, c2 = 0; // 统计数字d在答案序列和猜测序列中各出现多少次 | ||
- | for(int i = 0; i < n; i++) { | ||
- | if(a[i] == d) c1++; | ||
- | if(b[i] == d) c2++; | ||
- | } | ||
- | if(c1 < c2) B += c1; else B += c2; | ||
- | } | ||
- | printf(" (%d,%d)\n", A, B-A); | ||
- | } | ||
- | } | ||
- | return 0; | ||
- | } | ||
- | </code> | ||
- | <HTML><ul></HTML> | ||
- | <HTML><li></HTML><HTML><p></HTML>生成元($UVa1583$)<HTML></p></HTML> | ||
- | <HTML><p></HTML>预处理加散列表。比较简单,代码略。<HTML></p></HTML><HTML></li></HTML> | ||
- | <HTML><li></HTML><HTML><p></HTML>环状序列($UVa1584$)<HTML></p></HTML> | ||
- | <HTML><p></HTML>用 $ans$ 表示目前为止,字典序最小串在输入串中的起始位置,然后不断更新$ans$,一个值得注意的地方是,对于环形序列,采用他对字符串长度的$mod$值来表示它的相对位置。<HTML></p></HTML><HTML></li></HTML><HTML></ul></HTML> | ||
- | |||
- | <code c> | ||
- | #include<stdio.h> | ||
- | #include<string.h> | ||
- | #define maxn 105 | ||
- | |||
- | // 环状串s的表示法p是否比表示法q的字典序小 | ||
- | int less(const char* s, int p, int q) { | ||
- | int n = strlen(s); | ||
- | for(int i = 0; i < n; i++) | ||
- | if(s[(p+i)%n] != s[(q+i)%n]) | ||
- | return s[(p+i)%n] < s[(q+i)%n]; | ||
- | return 0; // 相等 | ||
- | } | ||
- | |||
- | int main() { | ||
- | int T; | ||
- | char s[maxn]; | ||
- | scanf("%d", &T); | ||
- | while(T--) { | ||
- | scanf("%s", s); | ||
- | int ans = 0; | ||
- | int n = strlen(s); | ||
- | for(int i = 1; i < n; i++) | ||
- | if(less(s, i, ans)) ans = i; | ||
- | for(int i = 0; i < n; i++) | ||
- | putchar(s[(i+ans)%n]); | ||
- | putchar('\n'); | ||
- | } | ||
- | return 0; | ||
- | } | ||
- | </code> | ||
- | ===== 注解与习题 ===== | ||
- | |||
- | <HTML><ul></HTML> | ||
- | <HTML><li></HTML><HTML><p></HTML>用''%%ASCII%%'' 编码表示字符<HTML></p></HTML><HTML></li></HTML> | ||
- | <HTML><li></HTML><HTML><p></HTML>进制转换与移位运算符<HTML></p></HTML><HTML></li></HTML> | ||
- | <HTML><li></HTML><HTML><p></HTML>补码表示法<HTML></p></HTML> | ||
- | <HTML><p></HTML>在大多数的计算机内部,整数采用的是补码表示法。<HTML></p></HTML><HTML></li></HTML> | ||
- | <HTML><li></HTML><HTML><p></HTML>思考题<HTML></p></HTML> | ||
- | <HTML><p></HTML>必要的存储量:有些时候不一定要开数组即可完成任务。<HTML></p></HTML><HTML></li></HTML> | ||
- | <HTML><li></HTML><HTML><p></HTML>黑盒测试<HTML></p></HTML> | ||
- | <HTML><p></HTML>算法竞赛一般采用黑盒测试。<HTML></p></HTML> | ||
- | <HTML><p></HTML>超时的原因:效率低;读取数据错误;程序死循环;程序崩溃但退出异常。<HTML></p></HTML><HTML></li></HTML> | ||
- | <HTML><li></HTML><HTML><p></HTML>在线评测系统 ($Online Judge,OJ$)<HTML></p></HTML> | ||
- | <HTML><p></HTML>西班牙$Valladolid$大学的$UVaOJ$<HTML></p></HTML><HTML></li></HTML><HTML></ul></HTML> | ||
- | |||
- | ====== 第四章 函数和递归 ====== | ||
- | |||
- | ===== 自定义函数和结构体 ===== | ||
- | |||
- | * 采用$struct$ 的写法 | ||
- | |||
- | <code c> | ||
- | struct Point{ double x,y;}; | ||
- | double dist(struct Point a,struct Point b) | ||
- | { | ||
- | return hypot(a.x-b.x, a.y-b.y); | ||
- | } | ||
- | </code> | ||
- | * 采用$typedef$的写法 | ||
- | |||
- | <code c> | ||
- | typedef struct{ double x,y;}Point; | ||
- | double dist(Point a,Point b) | ||
- | { | ||
- | return hypot(a.x-b.x, a.y-b.y); | ||
- | } | ||
- | </code> | ||
- | <HTML><ul></HTML> | ||
- | <HTML><li></HTML><HTML><p></HTML>素数判定<HTML></p></HTML> | ||
- | <HTML><p></HTML>''%%is_prime%%'' 的参数并不是''%%long long%%''型,因为在''%%n%%''很大时,这个函数并不能很快计算出结果。<HTML></p></HTML><HTML></li></HTML><HTML></ul></HTML> | ||
- | |||
- | <code c> | ||
- | int is_prime(int n) | ||
- | { | ||
- | if (n <= 1) return 0; | ||
- | int m = floor(sqrt(n) + 0.5); | ||
- | for (int i = 2; i<= m; i++) | ||
- | if(n % i == 0) return 0; | ||
- | return 1; | ||
- | } | ||
- | </code> |