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;
}

浙公网安备 33010602011771号