从一开始学筛法及其优化的时候就只是一知半解,所以需要用到其变化的时候就开始暴露问题。
顺便学了一下线性筛:
http://blog.youkuaiyun.com/xl2015190026/article/details/72859366
理应想到应用区间问题的解法的,思路都是前缀和。只不过跟数位有关的问题就用数位计数DP求前缀和,最简单的前缀和就是O(n)加起来。
这里的前缀和是指个数的前缀和,也就是所谓的一维差分算法,用于快速找区间内满足条件的数的个数。
区间问题是指多次询问一个区间里面满足特定条件的数的个数。
本题不是区间问题,因为既不是问数的个数,也不是单纯的只考虑每一个数,因此前缀和或是线段树都没有办法很好的解决。
但是由于题目的特殊性,所以可以转化成区间问题再来讨论求解。
代码
#include<stdio.h>
#include<math.h>
#include<vector>
#include<algorithm>
#include<string.h>
using namespace std;
const int maxn = 1000010;
int F[maxn];
vector<int>vec[10];
int cnt[10];
void init()
{
for(int i=2;i<maxn;i++) if(!F[i])
for(int j=i;j<maxn;j+=i) F[j]++;
for(int i=2;i<maxn;i++) if(F[i]>=3) vec[F[i]].push_back(i);
}
int solve()
{
int L,R;
scanf("%d %d",&L,&R);
int l,r;
l=lower_bound(vec[7].begin(),vec[7].end(),L)-vec[7].begin();
r=upper_bound(vec[7].begin(),vec[7].end(),R)-vec[7].begin();
if(r-l>=2) return 0*puts("7");
l=lower_bound(vec[6].begin(),vec[6].end(),L)-vec[6].begin();
r=upper_bound(vec[6].begin(),vec[6].end(),R)-vec[6].begin();
if(r-l>=2) return 0*puts("6");
l=lower_bound(vec[5].begin(),vec[5].end(),L)-vec[5].begin();
r=upper_bound(vec[5].begin(),vec[5].end(),R)-vec[5].begin();
if(r-l>=2) return 0*puts("5");
l=lower_bound(vec[4].begin(),vec[4].end(),L)-vec[4].begin();
r=upper_bound(vec[4].begin(),vec[4].end(),R)-vec[4].begin();
if(r-l>=2) return 0*puts("4");
l=lower_bound(vec[3].begin(),vec[3].end(),L)-vec[3].begin();
r=upper_bound(vec[3].begin(),vec[3].end(),R)-vec[3].begin();
if(r-l>=2) return 0*puts("3");
memset(cnt,0,sizeof(cnt));
for(int i=L;i<=R;i++) cnt[F[i]]++;
if(cnt[6]&&cnt[3]) return 0*puts("3");
if(cnt[2]&&cnt[4]) return 0*puts("2");
if(cnt[2]&&cnt[6]) return 0*puts("2");
if(cnt[4]&&cnt[6]) return 0*puts("2");
if(cnt[2]>=2) return 0*puts("2");
return 0*puts("1");
}
int main()
{
init();
//for(int i=0;i<=1000;i++) printf("F(%d):%d\n",i,F[i]);
int T;
scanf("%d",&T);
while(T--) solve();
return 0;
}