题意:
问你q次查询,每次查询给你n和k,问你从1到n中有多少数,这个数可以被大于等于k的质数的乘积所表示。
思考:
刚开始看到,感觉没啥想法,一看查询次数多应该是预处理出来,感觉用啥数论的结论了。其实不然,对于多次查询的题目,不一定都是需要全部预处理出来,也可以转化为在线去做。这道题,能否表示为>=k乘积也就是,一个数的最小质因子>=k。所以这就好办了,维护一个柱状数组,先对查询的n进行排序,然后如果当前的j<=n,就把j的最小质因子放进去,然后查询出来当前有多少个质因子>=k。然后再把这个答案记录到anw里面,最后输出即可。和我之前做的一个题目一样牛牛种花,这题就是对x先处理,然后看看y有多少个小的。
代码:
struct Node{
int n,k;
int id;
}node[N];
int r = 100;
int T,q;
int va[N];
int anw[N];
int minn[N];
int pri[N],st[N],cnt;
void init()
{
for(int i=2;i<=r;i++)
{
if(!st[i]) pri[++cnt] = i,minn[i] = i;
for(int j=1;pri[j]*i<=r;j++)
{
st[pri[j]*i] = 1;
minn[pri[j]*i] = pri[j];
if(i%pri[j]==0) break;
}
}
}
bool cmp(Node A,Node B)
{
return A.n<B.n;
}
int bit(int x)
{
return x&(-x);
}
int query(int x)
{
int sum = 0;
while(x)
{
sum += va[x];
x -= bit(x);
}
return sum;
}
void update(int x,int value)
{
while(x<=r)
{
va[x] += value;
x += bit(x);
}
}
signed main()
{
IOS;
init();
cin>>q;
for(int i=1;i<=q;i++)
{
int a,b;
cin>>a>>b;
node[i] = {a,b,i};
}
sort(node+1,node+1+q,cmp);
for(int i=1,j=2;i<=q;i++)
{
while(j<=node[i].n) update(minn[j++],1); //经典操作了
int ans = node[i].n-1-query(node[i].k-1); //减1是因为没算上1,1肯定是不选的
anw[node[i].id] = ans; //放进答案里面
}
for(int i=1;i<=q;i++) cout<<anw[i]<<"\n";
return 0;
}
总结:
多多积累经验呀,多多思考以前做过的题目类型。