题意:在小于n的范围内,找出所有最大除数为d的数。
思路:假设存在一个y满足题目条件,即y=k*d,那么我们可以分析出来 k一定为质数,而且k<=d,因为只有这样k才不能分解成两个大于1的数,如果一旦分成两个大于1的数a,b;那么a*d也是y的因子而且比d大了。既然这样的话,我们就可以通过素数筛预处理素数。
枚举每一个素数和d的乘积是否满足,那何时终止呢?(素数存入V数组
1.当v[i]*d>=n 不满足条件了,显然要终止了;
2.当v[i]是d的因子时(这个也保证了v[i]<d)此时也要终止了,但res++;
当d不是质数时,则d可以分成两个大于1的数,一个最小质数因子和另一个数,v[i]是最小质数因子时,此时乘积的最大除数还是 d,但当v[i]再大时,v[i]就会和另一个数相乘变成一个>d的数。
当d是质数时,那d只能分成1和d,当v[i]时d是, 乘积的最大除数还是 d,v[i]再大,那最大除数就成了v[i]了。
一点注意:噢,还有一点,就是素数筛的时候,筛选的上界并不是n(1e9),这也是一开始做这个没有注意到的,以为素数筛数组开不了。因为如果d是质数那么d*d就结束了,而且d*d要小于n,如果d不是质数,那么跑的它的最小质因子就结束了;综上,所以筛选的上界是sqrt(n),保险可以开大一点。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+7;
int T,n,d,psize;
ll v[maxn];
bool pd[maxn+1];
void work() {
psize=0;
pd[0]=true;
pd[1]=true;
for(int i=2; i<=maxn; ++i) {
if(!pd[i]) {
v[psize++]=i;
for(int j=2*i; j<=maxn; j+=i) {
pd[j]=true;
}
}
}
}
int main() {
scanf("%d",&T);
work();
while(T--) {
scanf("%d%d",&n,&d);
ll res=0;
for(int i=0;i<psize;++i){
if(v[i]*d>=n){
break;
}
res++;
if(d%v[i]==0){
break;
}
}
cout<<res<<endl;
}
return 0;
}