CF546D

Solution

容易发现答案就是 \([b+1,a]\) 所有数的质因子个数和。

考虑到多次询问,首先预处理出前缀质因子个数和,询问时直接输出 \(sum_b-sum_a\) 即可。

如何快速对一个数 \(x\) 分解质因子,首先我们可以进行一遍线性筛,因为每个合数只会被它最小质因子筛,于是可以处理出 \(f_i\) 表示 \(i\) 的最小质因子。然后对于 \(x\),若 \(x\not= 1\),则计数器加 \(1\),令 \(x=\frac {x}{f_x}\),继续循环直至 \(x=1\)

这题难度在于快速分解质因子,暴力 \(O(n\sqrt{n})\) 过不了,通过预处理最小质因子,可以避免大量不必要的判断。

Code

#include<bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define mkp make_pair
using namespace std;
using ll=long long;
using pii=pair<int,int>;
using pll=pair<ll,ll>;
using ull=unsigned long long;
inline void read(int &x){
  char ch=getchar();
  int r=0,w=1;
  while(!isdigit(ch))w=ch=='-'?-1:1,ch=getchar();
  while(isdigit(ch))r=(r<<1)+(r<<3)+(ch^48),ch=getchar();
  x=r*w;
}
const int N=5e6,M=1e6+7;
bool bb[N+7];
int prim[M],tot,f[N+7];
int qa[M],qb[M],mxa,sum[N+7];
void init(){
  for(int i=2;i<=N;i++){
    if(!bb[i])prim[++tot]=i,f[i]=i;
    for(int j=1;j<=tot;j++){
      if(i*prim[j]>N)break;
      bb[i*prim[j]]=1;f[i*prim[j]]=prim[j];
      if(i%prim[j]==0)break;
    }
  }
  for(int i=1;i<=mxa;i++){
    int j=i,s=0;
    while(j!=1)s++,j/=f[j];
    sum[i]=sum[i-1]+s;
  }
}
int main(){
  int T;read(T);
  for(int i=1;i<=T;i++)read(qa[i]),read(qb[i]),mxa=max(mxa,qa[i]);
  init();
  for(int i=1;i<=T;i++)printf("%d\n",sum[qa[i]]-sum[qb[i]]);
  return 0;
}
posted @ 2023-03-26 15:43  Epoch_L  阅读(23)  评论(0)    收藏  举报