Book--筛法求素数
废话不多说,就是开一个bool数组(较大),初始都赋为false,然后把非素数用2层循环找出非素数,赋为true。思路很简单。
首先上一个速敲版的:
for(int i = 2; i <= MAXN; i++) if( ! arr[i] ) for(int j = i * 2; j <= MAXN; j += i) arr[j] = 1; //表示是合数
for(int i = 2; i * i <= MAXN; i++) if( ! arr[i] ) for(int j = i * i; j <= MAXN; j += i) arr[j] = 1; //表示是合数
下面看看一个比较高效的:
#include <math.h> #include <stdio.h> #include <string.h> #include <iostream> using namespace std; #define MAXN 100000000 bool arr[MAXN+5]; void buildform() { memset(arr,0,sizeof(arr)); for(int i = 4 ; i <= MAXN ; i += 2)//先考虑2的倍数,为了配合下面的2层循环 { arr[i] = true; } int k = sqrt(1.0 * MAXN); for(int i = 3 ; i <= k ; i += 2)//只考虑奇数 { for(int j = i*i ; j<=MAXN ; j+=i) { arr[j] = true; } } return; }
从筛法素数表我们可以看到,它核心思想是:多角度看问题、从另一面解决问题往往高效。
最近看到”一个求一个数所有因数和“的问题。
由于输入的数据量巨大,所以一般的解法(即从1到n枚举相加)
肯定超时(设数据量为一百万,求某个数m时间为c*O(m),复杂度O(m),总复杂度很容易破亿数量级)
所以,换个角度,参考快速欧拉函数算法。
void facsum() { memset(arr,0,sizeof(arr)); for( int i = 1 ; i < MAXN ; i++) { for( int j = i + i ; j < MAXN ; j += i )//式子很灵活,若因数不包含本身则这么写,若包含则写int j = i; { arr[ j ] += i; } } }