素数
1、素性测试
1 bool is_prime(int x) 2 { 3 for(int i = 2; i * i <= x; i++) 4 { 5 if(n % i == 0)return false; 6 } 7 return x != 1;//x等于1是特例 8 }
2、约数枚举
1 vector<int> divisor(int n) 2 { 3 vector<int>res; 4 for(int i = 1; i * i <= n; i++) 5 { 6 if(n % i == 0) 7 { 8 res.push_back(i); 9 if(i != n / i)res.push_back(n / i); 10 } 11 } 12 return res; 13 }
3、整数分解
1 map<int, int> prime_factor(int n) 2 { 3 map<int, int>cnt; 4 for(int i = 2; i * i <= n; i++) 5 { 6 while(n % i == 0) 7 { 8 ++cnt[i]; 9 n /= i; 10 } 11 } 12 if(n != 1)cnt[n] = 1; 13 return cnt; 14 }
4、埃氏筛法
打表出10^6以内的素数
1 const int maxn = 1000000+10; 2 int prime[maxn]; 3 bool is_prime[maxn]; 4 int sieve(int n)//返回n以内素数的个数 5 { 6 int p = 0; 7 for(int i = 0; i <= n; i++)is_prime[i] = 1; 8 is_prime[0] = is_prime[1] = 0; 9 for(ll i = 2; i <= n; i++) 10 { 11 if(is_prime[i]) 12 { 13 prime[p++] = i; 14 for(ll j = i * i; j <= n; j += i)is_prime[j] = 0;//这里涉及i*i,必须使用long long 15 } 16 } 17 return p; 18 }
5、区间筛法
给定整数a和b,请问区间[a,b]内有多少个素数?
a< b<=10^12
b-a<=10^6
b以内的合数的最小质因数一定不超过sqrt(b)。如果有sqrt(b)以内的素数表的话,就可以把埃式筛法运用在[a,b]上了。也就是说,先分别做好[2,sqrt(b)]的表和[a,b]的表,然后从[2,sqrt(b)]的表中筛得素数的同时,也将其倍数从[a,b]的表中划去,最后剩下的就是区间[a,b]内的素数了。
1 typedef long long ll; 2 const int maxn = 1000000+10; 3 bool is_prime[maxn];//这是ab区间上的素数 4 bool is_prime_small[maxn];//这是(2,根号b)区间的素数 5 int sum_prime(ll a, ll b)//[a, b]区间内素数筛选 6 { 7 for(ll i = 0; i * i <= b; i++)is_prime_small[i] = 1; 8 for(ll i = 0; i <= b - a; i++)is_prime[i] = 1; 9 if(a < 2)a = 2;//注意这里 10 for(ll i = 2; i * i <= b; i++) 11 { 12 if(is_prime_small[i])//如果是小区间上的素数那就直接筛选小区间和大区间 13 { 14 for(ll j = 2 * i; j * j <= b; j += i)is_prime_small[j] = 0;//筛选小区间 15 16 for(ll j = max(2LL, (a + i - 1) / i) * i; j <= b; j += i)//j初始化的时候是ab区间中第一个i的倍数 17 is_prime[j - a] = 0; 18 } 19 } 20 int sum = 0; 21 for(ll i = 0; i <= b - a; i++)if(is_prime[i])sum++; 22 return sum; 23 }
越努力,越幸运