#include<bits/stdc++.h>
typedef long long ll;
using namespace std;


//埃氏筛,求素数,返回vector<ll>,时间复杂度O(nloglogn)
  vector<ll> zhishushai(ll n){
  vector<ll> primes;
  if(n<2)
    return primes;
  vector<bool> is_prime(n + 1, true);
  is_prime[0] = is_prime[1] = false;
  for (int i = 2; i * i <= n;i++){  //思想:从 2 开始,如果是
    if(is_prime[i]){                //质数,就把它所有倍数标记为合数。
      for (int j = i * i; j <= n;j+=i){//优化:只需要筛到 到 sqrt(n) 的质数即可
        is_prime[j] = false;           //因为大于 sqrt(n) 的质数的倍数在小于 sqrt(n) 的质数的倍数中已经被筛掉了。
      }
    }
  }
  for (int i = 2; i <= n;i++){
    if(is_prime[i])
      primes.push_back(1LL*i);
  }
  return primes;
}


//欧拉筛(线性筛),求素数,返回vector<ll>,时间复杂度O(n)
vector<ll> oulashai(int n){
  vector<ll> primes;
  if(n<2)
    return primes;
  vector<bool> is_prime(n + 1, true);
  is_prime[0] = is_prime[1] = 0;
  for (int i = 2; i <= n;i++){//思想:每个合数只被它的最小质因子筛掉一次,因此复杂度是线性的。
      if(is_prime[i])         //没有被筛掉的数就是质数
      primes.push_back(1LL*i);

      for(int p:primes){
        if(p*i>n)              //如果p*i>n,说明i的最小质因子已经大于sqrt(n),所以不需要再筛了
          break;
        is_prime[p * i] = false;//筛掉合数
        if(i%p==0)               //如果i能被p整除,说明p是i的最小质因子,那么i的倍数中,p*i已经被筛掉了,所以不需要再筛了
          break;
      } 
  }
  return primes;
}

int main(){
  int _ = 1;
  cin >> _;
  //vector<ll> primes=zhishushai(1000000);
  vector<ll> primes=oulashai(1000000);
  while(_--){
    int n;
    cin >> n;
    for (int i = 0; i < n; i++){
        cout<<1LL*primes[i]*primes[i+1]<<" ";
    }
  }

  return 0;
}

欧拉筛相比埃氏筛:

欧拉筛不会重复筛拥有同样两个因子的数,(eg:i=a*b=b*a,(a<b&&a,b<sqrt(n)),埃氏筛先遍历到a时,会让b*a,再把结果i筛掉,遍历到b时,会让a*b,再把结果i筛掉,这样会重复筛掉同一个数,所以引出了欧拉筛)

欧拉筛:每个合数只会被它的最小质因子筛掉一次

设合数 x,它的最小质因子是 p。
令 i=x/p。(x=p*i)

因为 p 是 x 的最小质因子,所以 i 的所有质因子都大于等于 p。

在欧拉筛内层循环中,当外层循环到 i 时,会从小到大枚举质数 p′:

  • 对于所有 p′<p,因为 p′ 小于 p,而 i 的所有质因子都 ≥p,所以 p′ 不可能整除 i,即 i % p' != 0,不会 break;

  • 当枚举到 p 时,标记 i * p = x;

  • 此时如果i%p==0,就 break,不再继续枚举更大的质数。

这样就保证了 x 只会被 i 和它的最小质因子 p 标记一次。

而如果 x被其他质因子q>p 标记,那么对应的 i′=x/q 一定含有质因子 p。当外层循环到 i′时,内层会先枚举到 p,此时 i' % p == 0,会直接 break,根本轮不到 q 去标记 x。所以 x 不会被重复标记。

题目链接:

Dashboard - Codeforces Round 1090 (Div. 4) - Codeforces

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐