默认计划
491人加入学习
(0人评价)
【研发工程师】C语言程序设计
价格 ¥ 970.00
该课程属于 名企研发核心能力课 请加入后再学习

数组与预处理:

函数内部定义的数组,是在栈区(并不会清空内存值),不初始化的话内部会有脏数据;

memset也能初始化数组。

 

数组性质:

int arr[100]静态数组,空间连续。

支持随机访问(下标访问)。

数组是相同变量的集合;

数组的地址,arr就是地址,也是&arr[0];

初始化int arr[2] = {5, 8};

 

数组通常表示两个信息:下标值和值

还有值的正负,三个信息。

 

-----------------------------------------------

素数筛用素数标记掉合数

标记一个范围内的数字是否为合数,没有标记的则为素数。

空间复杂度O(N),时间复杂度O(N * loglogN)(无限接近于O(N))

总体思想是用素数标记掉不是素数的数字,例如先知道了i是素数,则2i、3i、4i... ... 就都不是素数。

 

暴力算法:从2~N-1找i,能被N整除,就是合数。O(N)

for (int i = 2; i < n; i++) {
    if (n % i == 0)  return 0;
}
return 1;

 

优化为O(sqrt(N)) :

for (int i = 2; i * i <= n; i++) {
    if (n % i == 0)  return 0;
}
return 1;

 

但是如果遍历的话,嵌套了一层循环,时间复杂度变为O(N * sqrt(N)) ,不是很好。

------------------------------------------------

素数筛步骤:(默认都为0,标记合数为1)

①用prime[i]来标记i是否为合数

②标记为1的数字为合数,否则为素数,如:

prime[2] = 0表示素数

prime[4] = 1表示合数

③第一次知道2是素数1,则将2的倍数标记为1;

④向后找到第一个没有被标记的数字i

⑤将i的倍数全部标记为合数

⑥重复4~6步,直到标记完范围内的所有数字。

 

============================

开数组一般多开大一点,防止数组越界。

如:

#define MAX_N 100

int prime[MAX_N + 5] = {0};

初始化函数:

void init() {
    for (int i = 2; i <= MAX; i++) {
        if (prime[i]) continue; // 1: not prime, if(1) do nothing
        for (int j = 2 * i; j <= MAX; j += i) {
            prime[j] = 1;
        }
    }
}
int main() {
    init();
    // 遍历输出
    for (int i = 2; i < MAX_N; i++) {
        if (prime[i])    continue;
        cout << prime[i] << endl;
    }
    return 0;
}

===========================

优化:

void init() {
    for (int i = 2; i < MAX_N; i++) {
        if (prime[i])    continue; //如果为合数(标记为1的是合数)什么也不干
        prime[++prime[0]] = i;  //用prime[0]记录素数的个数,然后从prime[1]开始记录第一个素数,方便后续遍历用
        for (int j = 2 * i; j < MAX_N; j += i) {
            prime[j] = 1;
        }
    }
    return ;
}

++prime[0]  统计个数兼下标。

===========================

再优化:j = 2 * i;变成 i * i(减少一部分向下枚举的重复标记,正常思维肯定是向上枚举素数)

for (int j = i * i; j < MAX_N; j += i) {
    prime[j] == 1;
}

上面代码有问题 i * i很有可能导致int溢出

不建议int改long long,因为int的计算速度比long long运算速度快

所以好的方式是不变int,乘法改除法

for (int j = i; j < MAX_N / i; j++) {
    prime[j * i] = 1;
}

 

===========================

素数筛的框架思想能解决的问题:

100以内每个数字最小的素因子。

素因子:素数的因子,比如6的因子:1, 2, 3, 6;其中最小素因子为2。

 

#define MAX_N 100;

int prime[MAX_N + 5] = {0};

void init() {
    for (int i = 2; i <= MAX_N; i++) {
        if (prime[i]) continue;
        for (int j = i; j <= MAX_N; j += i) {
            if (prime[j]) continue;    // 求最大素因子注释掉此行
            prime[j] = i;
        }
    }
    return ;
}

int main() {
    init();
    for (int i = 2; i <= MAX_N; i++) {
        printf("min_fac[%d] = %d\n", i, prime[i]);
    }
    return 0;
}

 

HZOJ:191题目

 

数组作为函数参数在讲预处理里面

 

[展开全文]

数组的声明与初始化:

  栈区的数组需要自己初始化;

素数筛

  1、标记一个范围内的数字是否是合数,没标记的为素数

  2、空间复杂度为O(N),时间复杂O(N*loglogN)

   3、用素数去标记掉不是素数的数字, 假设i是素数, 则2 *i, 3*i ...都为合数;

  

int is_prime(int n) {
  if (n <= 1) return 0;
  for (int i = 2; i * i <= n; i++) {
    if (n % i == 0) return 0;
  }
  return 1;
}
#include <stdio.h>
#define MAX_N 100

int prime[MAX_N + 5] = {0};
void init() {
  for (int i = 2; i <= MAX_N; i++) {
    if (prime[i]) continue;
    prime[++prime[0]] = i;
    for (int j = 2 * i; j <= MAX_N; j += i) {
    //for (int j = i * i; j < MAX_N; j += i) {
    // for (int j = i; j <= MAX_N / i; j++) {
    //  prime[j * i] = 1;
      prime[j] = 1;
    }
  }
  return;
}

int main() {
  init();
  for (int i = 1; i <= prime[0]; i++) {
    printf("%d\n", prime[i]);
 // for (int i = 2; i <= MAX_N; i++) {
   // if (prime[i]) continue;
 //   i != 2 && printf(" ");
 //   printf("%d", i);
  }
  return 0;
}

/*  MAX_N 以内最小因子  */
#include <stdio.h>
#define MAX_N 100

int prime[MAX_N + 5] = {0};
void init() {
  for (int i = 2; i <= MAX_N; i++) {
    if (prime[i]) continue;
    for (int j = i; j <= MAX_N / i; j++) {
      if (prime[j * i]) continue;
      prime[j * i] = i;
    }
  }
  return;
}

int main() {
  init();
  for (int i = 2; i <= MAX_N; i++) {
    if (prime[i] == 0) printf("%d, %d\n", i, i), continue;
    printf("%d, %d\n", i, prime[i]);
  }
  return 0;
}
/*  MAX_N 以内最大素因子  */
#include <stdio.h>
#define MAX_N 100

int prime[MAX_N + 5] = {0};
void init() {
  for (int i = 2; i <= MAX_N; i++) {
    if (prime[i]) continue;
    for (int j = i; j <= MAX_N / i; j++) {
      
      prime[j * i] = i;
    }
  }
  return;
}

int main() {
  init();
  for (int i = 2; i <= MAX_N; i++) {
    if (prime[i] == 0) printf("%d, %d\n", i, i), continue;
    printf("%d, %d\n", i, prime[i]);
  }
  return 0;
}

 

[展开全文]

授课教师

C++算法工程师

课程特色

视频(31)