素数筛法及三分法介绍|青训营笔记

135 阅读1分钟

这是我参与「第四届青训营 」笔记创作活动的第11天

算法,不仅是后端必备,作为前端开发人员,也必须要懂得一些算法,这样不仅能够使得性能提升,也能够对不同的模块进行优化。因此,算法在开发中的地位显得越来越重要。本文为大家介绍素数筛法中的线性晒、欧拉筛以及快速幂、快速矩阵幂和三分法。

素数筛法

线性筛(最快)

时间复杂度:O(n)

int Mark[MAXSIZE];  
int prime[MAXSIZE];  
​
//判断是否是一个素数 Mark 标记数组 index 素数个数  
int Prime(){  
   int index = 0;  
   for(int i = 2; i < MAXSIZE; i++){  
       //如果未标记则得到一个素数  
       if(Mark[i] == 0) prime[++index] = i;  
       //标记目前得到的素数的i倍为非素数  
       for(int j = 1; j <= index && prime[j] * i < MAXSIZE; j++){  
           Mark[i * prime[j]] = 1;  
           if(i % prime[j] == 0) break;  
      }  
  }  
   return index;  
}
​
​

欧拉筛

时间复杂度:O(n)

原理:如果判断24是否为一个素数那么用埃氏筛的话起码会重复筛24三次(212,38,4*6),那欧拉筛就是在此基础上只筛一次就是其最小质因数与因一个合数的乘积。

#include <bits/stdc++.h>//欧拉筛
​
using namespace std;
bool A[100000001];
int prime[1000001];
​
int main() {
   int n, m;
   scanf("%d %d", &n, &m);
   int cnt = 0;
   for (int i = 2; i <= n; i++) {
       if (A[i] == false) {
           prime[++cnt] = i;
      }
       for (int j = 1; j <= cnt && i * prime[j] <= n; j++) {
           A[i * prime[j]] = true;
           if (i % prime[j] == 0) break;//最重要的一步
      }
  }
   for (int i = 0; i < m; i++) {
       int c;
       scanf("%d", &c);
       printf("%d\n", prime[c]);
  }
   return 0;
}

快速幂

最快的快速幂算法,运用了位运算大大加快运算速度。 通过位运算降低时间复杂度。

long long fastPower(long long baselong long power) {
   long long result = 1;
   while (power > 0) {
       if (power & 1) {//此处等价于if(power%2==1)
           result = result * base ;
      }
       power >>= 1;//此处等价于power=power/2
       base = (base * base) ;
  }
   return result;
}

矩阵快速幂

先修知识:线性代数 (狗头)

时间复杂度:O(log_2k)

struct matrix
{
   int n,m;   
   int e[105][105];
}
matrix a,b;
​
matrix mul(matrix a,matrix b)
{
   matrix ans;
   ans.n=a.n;
   ans.m=b.m;
   
   for(int i=1;i<=ans.m;i++)
  for(int j=1;j<=ans.m;j++)
           ans.e[i][j]=0;     //初始化
   
   for(int i=1;i<=a.n;i++)
       for(int j=1;j<=b.m;j++)
           for(int k=1;k<=a.m;k++)
               ans.e[i][j]=(ans.e[i][j]+(a.e[i][k]*b.e[k][j])%mod)%mod;//快速幂的取模就在这里了!
   return ans;
}
​
matrix power(matrix a,ll b)
{
   matrix ans;
   ans.n=a.n;
   ans.m=a.m;
   //初始化为单元矩阵
   for(int i=1;i<=ans.n;i++)
   for(int j=1;j<=ans.m;j++)
           if(i==j) 
               ans.e[i][j]=1;
   else 
               ans.e[i][j]=0;    
   
   while(b)
  {
       if(b&1)
           ans=mul(ans,a);
      a=mul(a,a);
       b>>=1;
  }
   return ans;
}

三分法

假设题意求单峰函数的最值点,那么每次取两个点:x = (2*l+r)/3 , y = l+(2*r)/3

若只有最大值,则 分为两种情况

  • f(x)>f(y) ,舍弃[y,r]
  • f(x)<f(y),舍弃[l,x]

image.png

while (abs(r - l) > exp) {
       double x = (2 * l + r) / 3, y = (l + 2 * r) / 3;
       if (f(x) < f(y)) {
           l = x;
      } else {
           r = y;
      }
  }


\