pat--算法初步

排序

选择排序

  思想:
  迭代n-1次,
  维持循环不变式:
  第k次迭代前
  前k-1个元素均是有序的。且前k-1是有序排列下最前面的k-1个元素。

插入排序

  思想:
  迭代n-1次
  维持循环不变式:
  第k次迭代前
  前k-1个元素均是有序的

C标准库的快速排序

  ...

散列

散列的定义与整数散列

  常用Hash函数介绍:
  - 除留余数法
  H(Key) = Key % mod,一般mod选择为一个素数。
  解决冲突:
  1. 线性探查法
  H(Key),H(Key)+1,...
  2. 平方探查法
  H(Key)+1^2, H(Key)-1^2,H(Key)+2^2, H(Key)-2^2,...
  3. 链地址

  一般下可直接使用标准库提供的设施

字符串hash初步

  ASCII中'a'的码值97,'A'是65,'0'是48。

递归

分治

迭代

贪心

简单贪心

区间贪心

二分

二分查找

二分法扩展

  对应的问题类型:单调区间寻找指定位置

快速幂

two pointers

什么是two pointers

归并排序

递归实现

  左半边有序
  右半边有序
  左右合并

迭代实现

快速排序

  选取主元
  按主元进行区间划分
  左边区间有序
  右边区间有序


  // 随机快排:避免特定输入下必然导致最差效率的情况
  生成指定范围[a,b]内的随机数
  #include <stdlib.h>
  srand((unsigned)time(NULL));
  int k = (int)round(1.0*rand()/RAND_MAX * (b-a) + a);   

其他高效技巧与算法

打表

活用递推

随机选择算法

入门篇--数学问题

简单数学

最大公约数与最小公倍数

最大公约数

  求解最大公约数:
  给定a,b均为正整数,求a,b的最大公约数
  - 令min,max,分别代表a,b中较小者和较大者
  - 1.gcd(a,b)=gcd(min, max % min),利用此公式将一个较大规模问题转化为一个较小规模同类问题
  - 2.gcd(a,0)=a。给出边界。
  int gcd(int a, int b)
  {
        if(b==0) return a;
        else return gcd(b, a%b);
  }

最小公倍数

  正整数a,b的最小公倍数 = (ab)/(ab的最大公约数)

分数的四则运算

分数的表示和化简

分数的表示

  假分数
  struct Fraction
  {
        int up, down;
  };

  - 使down为非负数。如分数为负,令分子up为负即可。
  - 如该分数恰为0,则规定其分子为0,分母为1。
  - 分子和分母没有除了1以外的公约数。

分数的化简

  主要用来使Fraction变量满足分数表示的三项规定
  - 如分母down为负数,则令分子up和分母down都变为相反数
  - 如分子up为0,则令分母down为1
  - 约分,求分子绝对值和分母绝对值的最大公约数d,令分子,分母同时除以d

分数的输出

  - 输出分数前,先对其化简
  - 如分数r的分母down为1,说明该分数是整数,一般作为整数输出
  - 如分数r的分子绝对值大于分母,按带分数形式输出
  printf("%d %d/%d", r.up / r.down, abs(r.up) % r.down, r.down)

素数

  素数又称质数,指除了1和本身之外,不能被其他整数除的一类数。
  对任意除了1的正整数,不是素数,就是合数。
  1既不是素数,也不是合数

素数的判断

  加快素数的判定
  如在[2, n-1]中存在n的约数,设为k
  即n%k == 0
  则由k *(n/k)==n可知,
  n/k也是n的一个约数
  且k与n/k中一定满足其中一个小于等于sqrt(n),另一个大于等于sqrt(n)
  只需要判定n能否被2,3,...,(int)sqrt(n)中的一个整除,即可判定n是否为素数,算法复杂度O(sqrt(n))

素数表的获取

方法1

  对范围内每个数,依次使用上述素数判别进行判别

方法2

  1. 2是素数,去掉所有2的倍数
  2. 3依然存在,故是素数,去掉所有3的倍数
  3.下一个存在的是5,是素数,去掉所有5的倍数
  ...
  该算法求解范围内所有数中素数子集效率较高

质因子分解

  正因子分解指将一个正整数n写成一个或多个质数的乘积的形式
  以下讲解针对大于1的正整数
  由于每个质因子可不止出现一次,定义结构体factor存放质因子及其个数
  struct factor
  {
        // 质因子
        int x;
        // 个数
        int cnt;
  }fac[10];

  对一个int型范围的数,fac数组大小到10即可

  对一个正整数n来说,
  如它存在[2,n]范围内的质因子,
  要么这些质因子全部小于等于sqrt(n)
  要么只存在一个大于sqrt(n)质因子

  质因子分解:
  - 枚举[1, sqrt(n)]范围内所有质因子p,判断p是否是n的因子
  如果p是n的因子,给fac数组增加质因子p,初始化其个数为0
  只要p还是n的因子,就让n不断除以p,每次操作令p的个数加一,直到p不再是n的因子
  如果p不是n的因子,直接跳过
  - 如在上面步骤后,n仍然大于1,说明n有且仅有一个大于sqrt(n)的质因子
  把这个质因子加入fac,令其个数为1
  时间复杂度sqrt(n)

大整数运算

  对A+B
  如A和B有1000个数位

大整数的存储

  struct bign
  {
        int d[1000];
        int len;
        bign()
        {
              memset(d, 0, sizeof(d));
              len = 0;
        }
  };

  为了处理的方便,一般数组高索引位存储十进制形式的高位,索引0存储十进制下的个位
  输入大整数时,一般先用字符串读入
  再把字符串另存为bign结构体

大整数比较

大整数的四则运算

加法

  低位相加,进位

减法

  大数减去小数,余量确定时额外看下一位是否要给予增量,如果下一位两者相等,则需要持续往下看,直到看到不同

乘法

  从低位到高位迭代
  每次迭代处理
  计算迭代位和乘数1相乘结果+之前累积余量,得到结果的低位作为本位结果,减去低位余量作为累积余量继续迭代

除法

扩展欧几里得算法

扩展欧几里得算法

ax+by=c求解

ax ≡ c(modm)

  a≡b(mod m),或记为a≡b(m)
  即为(a-b)%m=0
posted @ 2020-08-21 01:44  raindayinrain  阅读(219)  评论(0编辑  收藏  举报