基础_2

来源:互联网 发布:程序员考试真题及答案 编辑:程序博客网 时间:2024/05/16 09:10

参考:《算法竞赛入门经典》

一、浮点数的问题(尽量避免浮点运算)

浮点数的运算(或函数)有可能存在误差——不是一定存在,但经常都会

比如在经过大量计算后,由于误差的影响,整数 1 变成了 0.9999999999

1、floor 向下取整

floor(3.14) = 3
floor(9.999999) = 9
floor(-3.14) = -4
floor(-9.999999) = -10

floor(1.0) = 1

floor(x + 0.5) 即将下取整改为四舍五入形式

2、ceil 向上取整

floor(3.14) = 4
floor(9.999999) = 10
floor(-3.14) = -3
floor(-9.999999) = -9

floor(1.0) = 1

二、一些数学公式

1、三角形面积公式

海伦公式

p = (a + b + c) / 2.0

S = sqrt(p * (p - a) * (p - b) * (p - c))


2、圆台体积公式:(1.0/3.0)* PI * h * (R * R+r * r+R * r)

π的宏定义

#define PI acos(-1.0)#define PI (atan(1.0) * 4.0)


三、

如果要从数组 a 复制 k 个元素到数组 b,可以这样做:memcpy(b, a, sizeof(int) * k)

当然了,如果数组 a 和 b 都是浮点型的,复制时要写成 memcpy(b, a, sizeof(double) * k)

如果需要把数组 a 全部复制到数组 b 中,可以写得简单一些:memcpy(b, a, sizeof(a))


四、

C 语言中,有一些字符直接表示出来不方便,例如回车符——它是 '\n',而空字符是 '\0',它也是 C 语言中字符串的结束标志

其他例子包括 '\\'(注意必须有两个反斜线)、'\''(这个是单引号),甚至还有的字符有两种写法:'\"' 和 '"' 都表示双引号

像这种以反斜线开头的字符称为转义序列


五、

strchr 函数:char *strchr(const char* _Str,char _Val)

功能:查找字符串_Str中首次出现字符_Val的位置
说明:返回首次出现_Val的位置的指针,返回的地址是被查找字符串指针开始的第一个与Val相同字符的指针,如果Str中不存在Val则返回NULL。


strcat 函数原型:extern char *strcat(char *dest, const char *src)
功能:把src所指字符串添加到dest结尾处(覆盖dest结尾处的'\0')
说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串
返回指向dest的指针


六、

用编译选项 -Wall 编译程序时,会给出很多(但不是所有)警告信息,以帮助程序员查错


七、用 fgets 而不是 gets

gets 和它的兄弟 fgets 差别比较大:它的用法是 gets(s),没有指明读取的最大字符数

这里就出现了一个潜在的问题:gets 将不停地往 s 里塞东西,而不管塞不塞得下!难道 gets 函数不去管 s 的可用空间有多少吗?你还真说对了


提示1:

C 语言并不禁止程序读写“非法内存”

例如你声明的是 char s[100],你完全可以赋值 s[10000] = 'a'(甚至 -Wall 也不会警告),但后果自负


提示2:

C 语言中的 gets(s) 存在缓冲区溢出漏洞,不推荐使用


解决“输入中有空格”的问题,我们选择的是 fgets 函数,它可以一次性读取一整行,最为方便


例:求最长回文子串

#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <queue>#include <vector>#include <stack>#include <map>#include <set>#include <cmath>#include <cctype>#include <ctime>using namespace std;#define REP(i, n) for (int i = 0; i < (n); ++i)typedef long long ll;typedef pair<int, int> Pair;const int INF = 0x7fffffff;const int maxn = 5000 + 10;char buf[maxn], str[maxn];int pos[maxn];int main() {#ifdef __AiR_H    freopen("in.txt", "r", stdin);#endif // __AiR_H    while (fgets(buf, sizeof(str), stdin)) {        int cnt = 0, Max = 0, Left = 0, Right = 0;        int len = strlen(buf);        REP(i, len) {            pos[cnt] = i;            if (isalpha(buf[i])) { str[cnt++] = toupper(buf[i]); }        }        REP(i, cnt) {            for (int j = 0; i - j >= 0 && i + j < cnt; ++j) {                if (str[i - j] != str[i + j]) { break; }                if (j * 2 + 1 > Max) {                    Max = j * 2 + 1; Left = pos[i - j]; Right = pos[i + j];                }            }            for (int j = 0; i - j >= 0 && i + j + 1 < cnt; ++j) {                if (str[i - j] != str[i + j + 1]) { break; }                if (j * 2 + 2 > Max) {                    Max = j * 2 + 2; Left = pos[i - j]; Right = pos[i + j + 1];                }            }        }        for (int i = Left; i <= Right; ++i) {            printf("%c", buf[i]);        }        printf("\n");    }#ifdef __AiR_H    printf("Time used = %.2fs\n", (double)clock() / CLOCKS_PER_SEC);#endif // __AiR_H    return 0;}


七、

printf("%d %o %x\n", a, a, a);

将把整数 a 分别按照十进制、八进制和十六进制输出


八、编写函数时,应尽量保证它能对任何合法参数都能得到正确的结果。如若不然,应在显著位置标明函数的缺陷,以避免误用

例、孪生素数

#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <queue>#include <vector>#include <stack>#include <map>#include <set>#include <cmath>#include <cctype>#include <ctime>#include <cassert>using namespace std;#define REP(i, n) for (int i = 0; i < (n); ++i)typedef long long ll;typedef pair<int, int> Pair;const int INF = 0x7fffffff;bool is_prime(int x);int main() {#ifdef __AiR_H    freopen("in.txt", "r", stdin);#endif // __AiR_H    int m;    scanf("%d", &m);    for (int i = m - 2; i >= 3; --i) {        if (is_prime(i) && is_prime(i + 2)) {            printf("%d %d\n", i, i + 2); break;        }    }#ifdef __AiR_H    printf("Time used = %.2fs\n", (double)clock() / CLOCKS_PER_SEC);#endif // __AiR_H    return 0;}bool is_prime(int x) {    assert(x >= 0);    if (x == 1) { return false; }    int m = floor(sqrt(x) + 0.5);    for (int i = 2; i <= m; ++i) {        if (x % i == 0) { return false; }    }    return true;}

除了特判 n == 1 的情况,程序中还使用了变量 m,一方面避免了每次重复计算 sqrt(x)

另一方面也通过四舍五入避免了浮点误差——如果 sqrt “不小心”把某个本应是整数的值弄成了 xxx.99999,也将被修正

但直接写 m = sqrt(x) 的话那个 “.99999” 会被无情地截掉

最后,程序使用了 cassert 中的 assert 宏来限制非法的函数调用:当 x >= 0不成立时,程序将异常终止,并给出提示信息

检查非法参数是很有用的的:当算法很复杂时,一不小心就会用非法参数调用某些自定义函数,如果函数不对参数进行检查,则很可能让程序得到一个荒唐的结果

如果函数调用关系非常复杂,是难以查出错误的根源的

如果每个函数都检查参数,就能较快地找出“罪魁祸首”


提示:编程时合理地利用 assert 宏,将给调试带来很大的方便


总而言之,在实际的系统中,“一个地方的参数错误就引起整个程序异常退出”是不可取的,在编写和调试算法程序中,assert 会“迫使”我们编写出更高质量的程序


九、Vijos P1333 Cantor表

#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <queue>#include <vector>#include <stack>#include <map>#include <set>#include <cmath>#include <cctype>#include <ctime>#include <cassert>using namespace std;#define REP(i, n) for (int i = 0; i < (n); ++i)typedef long long ll;typedef pair<int, int> Pair;const int INF = 0x7fffffff;int main() {#ifdef __AiR_H    freopen("in.txt", "r", stdin);#endif // __AiR_H    int N;    while (scanf("%d", &N) != EOF) {        int s = 0, k = 1;        while (1) {            s += k;            if (s >= N) {                if (k & 1) {                    printf("%d/%d\n", s - N + 1, k - s + N); break;                }                printf("%d/%d\n", k - s + N, s - N + 1); break;            }            ++k;        }    }#ifdef __AiR_H    printf("Time used = %.2fs\n", (double)clock() / CLOCKS_PER_SEC);#endif // __AiR_H    return 0;}


#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <queue>#include <vector>#include <stack>#include <map>#include <set>#include <cmath>#include <cctype>#include <ctime>#include <cassert>using namespace std;#define REP(i, n) for (int i = 0; i < (n); ++i)typedef long long ll;typedef pair<int, int> Pair;const int INF = 0x7fffffff;int main() {#ifdef __AiR_H    freopen("in.txt", "r", stdin);#endif // __AiR_H    int N;    while (scanf("%d", &N) != EOF) {        int k = (int)floor((sqrt(8.0 * N + 1) - 1) / 2 - 1e-9) + 1;        int s = k * (k + 1) / 2;        if (k & 1) {            printf("%d/%d\n", s - N + 1, k - s + N); continue;        }        printf("%d/%d\n", k - s + N, s - N + 1);    }#ifdef __AiR_H    printf("Time used = %.2fs\n", (double)clock() / CLOCKS_PER_SEC);#endif // __AiR_H    return 0;}


十、三角形有向面积



UVa 143 Orchard Trees

注意:树的坐标 (x,y) 的值为区间 [1, 99] 内的整数

#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <queue>#include <vector>#include <stack>#include <map>#include <set>#include <cmath>#include <cctype>#include <ctime>#include <cassert>using namespace std;#define REP(i, n) for (int i = 0; i < (n); ++i)#define eps 1e-9typedef long long ll;typedef pair<int, int> Pair;const int INF = 0x7fffffff;double x_0, y_0, x_1, y_1, x_2, y_2;int x_left, y_left, x_right, y_right;double area2(double _x_0, double _y_0, double _x_1, double _y_1, double _x_2, double _y_2) {    return (_x_0 * _y_1 - _x_1 * _y_0) + (_x_1 * _y_2 - _x_2 * _y_1) + (_x_2 * _y_0 - _x_0 * _y_2);}bool judge(double x, double y);int main() {#ifdef __AiR_H    freopen("in.txt", "r", stdin);#endif // __AiR_H    while (scanf("%lf %lf %lf %lf %lf %lf", &x_0, &y_0, &x_1, &y_1, &x_2, &y_2) != EOF) {        if (x_0 + y_0 + x_1 + y_1 + x_2 + y_2 < eps) { break; }        double t = min(x_0, min(x_1, x_2)); x_left = max(1, (int)ceil(t));        t = max(x_0, max(x_1, x_2)); x_right = min(99, (int)floor(t));        t = min(y_0, min(y_1, y_2)); y_left = max(1, (int)ceil(t));        t = max(y_0, max(y_1, y_2)); y_right = min(99, (int)floor(t));        int ans = 0;        for (int i = x_left; i<= x_right; ++i) {            for (int j = y_left; j <= y_right; ++j) {                if (judge((double)i, (double)j)) { ++ans; }            }        }        printf("%4d\n", ans);    }#ifdef __AiR_H    printf("Time used = %.2fs\n", (double)clock() / CLOCKS_PER_SEC);#endif // __AiR_H    return 0;}bool judge(double x, double y) {    double t = fabs(area2(x_0, y_0, x_1, y_1, x_2, y_2));    double a = fabs(area2(x, y, x_1, y_1, x_2, y_2));    double b = fabs(area2(x_0, y_0, x, y, x_2, y_2));    double c = fabs(area2(x_0, y_0, x_1, y_1, x, y));    if (fabs(t - a - b - c) < eps) { return true; }    return false;}


0 0
原创粉丝点击