样例解释:
3
!
/
1
!
=
2
∗
3
=
>
a
n
s
=
2
3!/ 1!=2*3=>ans=2
3!/1!=2∗3=>ans=2
6
!
/
3
!
=
4
∗
5
∗
6
=
2
∗
2
∗
2
∗
3
∗
5
=
>
a
n
s
=
5
6!/3!=4*5*6=2 * 2* 2*3*5=>ans=5
6!/3!=4∗5∗6=2∗2∗2∗3∗5=>ans=5
思路:
对1~5e6的每个数进行质因数计数,求前缀和,然后就可以O(1)输出ans了。
设pnum[i]是i的质因子的个数,i = a * b,则有pnum[i] = pnum[a] + pnum[b]。
举个例子:
36
=
4
∗
9
,
则
p
n
u
m
[
36
]
=
p
n
u
m
[
4
]
+
p
n
u
m
[
9
]
=
2
∗
2
=
4
36=4*9,则pnum[36]=pnum[4]+pnum[9]=2*2=4
36=4∗9,则pnum[36]=pnum[4]+pnum[9]=2∗2=4
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define ms(x,a) memset(x,a,sizeof(x))
using namespace std;
const int maxn = 5e6 + 10;
const ll mod = 1e9 + 7;
int n,m;
int cnt;
bool v[maxn];
ll p[maxn],sm[maxn];
void get_pnum(int x)
{
int y = x;
for(int i = 1; p[i] * p[i] <= x; i++)
{
while(x % p[i] == 0)
{
sm[y]++;
x /= p[i];
if(sm[x])
{
sm[y] += sm[x];
return ;
}
}
}
if(x > 1)sm[y]++;
return ;
}
void Prime()
{
cnt = 0;
ms(p,0);
ms(v,0);
ms(sm,0);
v[1] = 1;
for(int i = 2; i < maxn; i++)
{
if(!v[i])
{
p[++cnt] = i;
}
for(int j = 1; j <= cnt && p[j] * i <= maxn; j++)
{
v[i * p[j]] = 1;
if(i % p[j] == 0)
break;
}
}
for(int i = 1; i < maxn; i++)
{
get_pnum(i);
}
for(int i = 1; i < maxn; i++)
{
sm[i] += sm[i - 1];
}
}
void solve(){
Prime();
int t;
scanf("%d",&t);
for(int ca = 1; ca <= t; ca++)
{
scanf("%d%d",&n,&m);
printf("%lld\n",sm[n] - sm[m]);
}
return ;
}
int main()
{
solve();
return 0;
}
//Dawn_Exile