素数

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 }

 

posted @ 2018-04-12 20:55  _努力努力再努力x  阅读(625)  评论(0编辑  收藏  举报