Problem Description
A positive proper divisor is a positive divisor of a number n, excluding n itself. For example, 1, 2, and 3 are positive proper divisors of 6, but 6 itself is not.
Peter has two positive integers n and d. He would like to know the number of integers below n whose maximum positive proper divisor is d.
Peter has two positive integers n and d. He would like to know the number of integers below n whose maximum positive proper divisor is d.
Input
There are multiple test cases. The first line of input contains an integer T (1≤T≤106), indicating the number of test cases. For each test case:
The first line contains two integers n and d (2≤n,d≤109).
The first line contains two integers n and d (2≤n,d≤109).
Output
For each test case, output an integer denoting the answer.
Sample Input
9
10 2
10 3
10 4
10 5
10 6
10 7
10 8
10 9
100 13
Sample Output
1
2
1
0
0
0
0
0
4
解题思路:题目的意思就是求[2,n-1]内满足"最大真约数"为d的数字的个数。首先,这些数必然是d的倍数,且这个倍数必须是质数,否则会产生比d更大的约数;d为素数时,这个倍数最大只能是d,否则会使得最大真约数超过d;且这个倍数最大只能为(n-1)/d,否则会使得d*这个倍数后的结果大于n-1;还有一点非常重要,就是这个倍数最大只能是d的最小素因子,否则就会使得最大真约数超过d。假设这个倍数最大为border,则border=min(min(d,(n-1)/d),d的最小素因子)。由于d的最小素因子一定不超过sqrt(1e9)≈31623,所以我们只需将素数筛到31650-1即可。
AC代码(733ms):
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=31650;//只需得到sqrt(1e9)=31622.8(取比31622.8大一点的整数31650)内的所有质数即可 4 int t,n,d,cnt=0,prime[maxn];bool isp[maxn]; 5 void euler_sieve(){ 6 memset(isp,true,sizeof(isp)); 7 isp[0]=isp[1]=false; 8 for(int i=2;i<maxn;++i){ 9 if(isp[i])prime[cnt++]=i; 10 for(int j=0;j<cnt&&i*prime[j]<maxn;++j){ 11 isp[i*prime[j]]=false; 12 if(i%prime[j]==0)break; 13 } 14 } 15 } 16 int main(){ 17 euler_sieve(); 18 while(~scanf("%d",&t)){ 19 while(t--){ 20 scanf("%d%d",&n,&d); 21 int num=0,border=min(d,(n-1)/d); 22 for(int i=0;prime[i]<=border;++i){ 23 num++; 24 if(d%prime[i]==0)break;//至多找到d的最小质因子即可 25 } 26 printf("%d ",num); 27 } 28 } 29 return 0; 30 }