数组与预处理:
函数内部定义的数组,是在栈区(并不会清空内存值),不初始化的话内部会有脏数据;
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题目
数组作为函数参数在讲预处理里面