hdu 5750 Dertouzos(最大真约数、最小素因子)

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.

Input

There are multiple test cases. The first line of input contains an integer T (1T106), indicating the number of test cases. For each test case:
The first line contains two integers n and d (2n,d109).

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\n",num);
27         }
28     }
29     return 0;
30 }

 

posted @ 2018-08-17 08:00  霜雪千年  阅读(238)  评论(0编辑  收藏  举报