分析:用类似均摊的方法在遍历素数的时候加上n/d这个限制会优化。
代码:
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#include<math.h>
#include<vector>
#include<string>
#include<stdio.h>
#include<cstring>
#include<iostream>
#include<algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int N=40010;
const int mod=100000000;
const int MOD1=1000000007;
const int MOD2=1000000009;
const double EPS=0.00000001;
typedef long long ll;
const ll MOD=1000000007;
const int MAX=2000000010;
const ll INF=1ll<<55;
const double pi=acos(-1.0);
typedef double db;
typedef unsigned long long ull;
int k,a[N],q[N],f[N];
void deal(int n) {
int i,j;k=0;
for (i=2;i<=n;i++) {
if (!q[i]) a[++k]=i;
for (j=1;j<=k;j++) {
if (a[j]*i>n) break ;
q[a[j]*i]=1;
if (i%a[j]==0) break ;
}
}
}
int main()
{
int i,t,l,r,mid;
ll n,d,g;
scanf("%d", &t);
deal(40000);
while (t--) {
scanf("%I64d%I64d", &n, &d);
if (d>=n||d*2ll>=n) printf("0\n");
else {
for (i=1;i<=3450&&a[i]<=n/d;i++)
if (a[i]>d||d%a[i]==0) break ;
if (a[i]>d) g=1ll*a[i-1];
else g=1ll*a[i];
l=1;r=k;mid=(l+r)>>1;
while (l+1<r)
if (1ll*a[mid]>g||1ll*a[mid]*d>=n) { r=mid;mid=(l+r)>>1; }
else { l=mid;mid=(l+r)>>1; }
printf("%d\n", l);
}
}
return 0;
}