想法型数论题,题意很简单,就不多说了,首先想的时候认为算出所有数字的质因子个数会超时就没多想,结果跪了好久,最后仔细一想发现需要的时间也不多才想到该怎么做。
本题的突破点是,每个数字的质因子的个数只可能在8以下,非常小,打表算出每个数字的质因子的个数之后,记录下每个数字之下质因子个数是1~8的数的个数分别是多少个,然后R和L的这写记录数做差之后就知道R和L之间质因数个数是1~8之间的数分别有多少个,再加上几个判断就ok~
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <functional>
#include <cstdio>
#include <queue>
#include <map>
#include <algorithm>
#include <stack>
#include <utility>
typedef long long ll;
using namespace std;
const int mx = 1000009;
const int N = 1009;
int p[mx >> 1],cnt;
bool tage[mx];
int a[mx],num[mx][10],gc[10];
void get_prime()
{
int i,j,k;
cnt = 0;
memset(num,0,sizeof(num));
memset(a,0,sizeof(a));
memset(tage,false,sizeof(false));
for(i = 2; i < mx; i++)
{
if(!tage[i]) p[cnt++] = i;
for(j = 0; j < cnt && i * p[j] < mx; j++)
{
tage[i * p[j]] = 1;
if(i % p[j] == 0)
break;
}
}
for(i = 0;i < cnt;i++)
{
k = p[i];
while(k < mx)
{
a[k]++;
k += p[i];
}
}
for(i = 2; i < mx; i++)
{
// printf("i = %d a =%d \n",i,a[i]);
for(j = 1; j < 10; j++)
{
if(a[i] == j)
num[i][j] = num[i - 1][j] + 1;
else
num[i][j] = num[i - 1][j];
}
}
}
int main ()
{
int i,j,L,R,T,ans;
get_prime();
scanf("%d",&T);
while(T--)
{
ans = 0;
scanf("%d%d",&L,&R);
for(i = 1; i < 10; i++)
gc[i] = num[R][i] - num[L - 1][i];
for(i = 9; i > 0 && !ans; i--)
if(gc[i] > 1)
ans = i;
if(gc[4] && gc[8])
ans = max(ans,4);
if(gc[4] && gc[2])
ans = max(ans,2);
if(gc[2] && gc[8])
ans = max(ans,2);
if(ans == 0)
ans = max(ans,1);
printf("%d\n",ans);
}
}