Description
小X 是一位热爱数学的男孩子,在茫茫的数字中,他对质数更有一种独特的情感。小X 认为,质数是一切自然数起源的地方。
在小X 的认知里,质数是除了本身和1 以外,没有其他因数的数字。
但由于小X 对质数的热爱超乎寻常,所以小X 同样喜欢那些虽然不是质数,但却是由两个质数相乘得来的数。
于是,我们定义,一个数是小X 喜欢的数,当且仅当其是一个质数,或是两个质数的乘积。
而现在,小X 想要知道,在L 到R 之间,有多少数是他喜欢的数呢?
在小X 的认知里,质数是除了本身和1 以外,没有其他因数的数字。
但由于小X 对质数的热爱超乎寻常,所以小X 同样喜欢那些虽然不是质数,但却是由两个质数相乘得来的数。
于是,我们定义,一个数是小X 喜欢的数,当且仅当其是一个质数,或是两个质数的乘积。
而现在,小X 想要知道,在L 到R 之间,有多少数是他喜欢的数呢?
Input
第一行输入一个正整数Q,表示询问的组数。
接下来Q 行。包含两个正整数L 和R。保证L≤R。
接下来Q 行。包含两个正整数L 和R。保证L≤R。
Output
输出Q 行,每行一个整数,表示小X 喜欢的数的个数。
solution
大家学习一个东西,叫做线性筛,时间复杂度为O(n)。
点这里→→→→→→→→↑↑↑←←←←←←←←点这里
理解之后,这题O(1)过。
代码
const p=10000000; var n,l,r,nm:longint; sum,prime,bo,boo:array [0..10000001] of longint; procedure try1; var i,j:longint; begin fillchar(bo,sizeof(bo),0); fillchar(boo,sizeof(boo),0); fillchar(sum,sizeof(sum),0); nm:=0; for i:=2 to p do if bo[i]=0 then begin inc(nm); prime[nm]:=i; j:=1; boo[i]:=1; while (j<=nm) and (i*prime[j]<=p) do begin bo[i*prime[j]]:=1; boo[i*prime[j]]:=1; inc(j); end; end else begin j:=1; while (j<=nm) and (i*prime[j]<=p) do begin bo[i*prime[j]]:=1; if i mod prime[j]=0 then break; inc(j); end; end; for i:=1 to p do sum[i]:=sum[i-1]+boo[i]; end; procedure init; var i:longint; begin readln(n); for i:=1 to n do begin readln(l,r); writeln(sum[r]-sum[l-1]); end; end; begin assign(input,'prime.in'); assign(output,'prime.out'); reset(input); rewrite(output); try1; init; close(input); close(output); end.
本文介绍了一种使用线性筛法解决寻找特定区间内质数及其两质数乘积的方法,通过O(n)预处理,实现了O(1)查询效率。文中详细解释了算法流程,并提供了完整的代码实现。
406

被折叠的 条评论
为什么被折叠?



