随便推导下, 令y=xd, 如果d是y的maximum positive proper divisor, 显然要求x是y的最小质因子. 令mp(n)表示n的最小质因子, 那么就有x≤mp(d), 同时有y<n, 那么x≤⌊dn−1⌋. 于是就是计算有多少个素数x满足x≤min{mp(d),⌊dn−1⌋}.
当d比较大的时候, ⌊dn−1⌋比较小, 暴力枚举x即可. 当d比较小的时候, 可以直接预处理出答案. 阈值设置到106∼107都可以过.
#include<bits/stdc++.h>
#define LL long long
#define bug puts("*********")
using namespace std;
const int N=1100000;
bool vis[N];
int num;
int sum[N];
int prim[N];
void init(){
int m=1000000;
memset(vis,1,sizeof(vis));
vis[0]=0;
vis[1]=0;
for(int i=2;i<=1000;i++){
if(vis[i]){
for(int j=i*i;j<=m;j+=i){
vis[j]=0;
}
}
}
num=0;
for(int i=1;i<=1000000;i++){
if(vis[i]){
prim[num++]=i;
}
}
}
int main(){
int t;
int n,m;
num=0;
init();
while(~scanf("%d",&t)){
///必须满足 使m为最大约数(除了本身)
///就必须满足y=a*m a一定<= m的最小质因子,否则就不能满足上面的条件了
///同时还要满足 y< n 即 y<=n-1 即a<= (n-1)/m
///上述范围取最下即可
while(t--){
scanf("%d%d",&n,&m);
int d=(n-1)/m;
int a=100000000;///m的最小质约数
for(int i=0;;i++){
if(prim[i]>d)break;
if(m%prim[i]==0){
a=prim[i];break;
}
}
int cnt=0;
for(int i=0;prim[i]<=a&&prim[i]<=d;i++){
cnt++;
}
printf("%d\n",cnt);
}
}
return 0;
}