HDU 2588 GCD 【Euler + 暴力技巧】

本文探讨了一道关于最大公约数(GCD)的问题,旨在找出1到N范围内有多少个整数X,使得GCD(X,N)大于等于M。通过巧妙的数学分析,将问题转化为求解特定条件下互质对的数量,最终利用欧拉函数快速得出答案。

任意门:http://acm.hdu.edu.cn/showproblem.php?pid=2588

GCD

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3608    Accepted Submission(s): 1954


Problem Description
The greatest common divisor GCD(a,b) of two positive integers a and b,sometimes written (a,b),is the largest divisor common to a and b,For example,(1,2)=1,(12,18)=6.
(a,b) can be easily found by the Euclidean algorithm. Now Carp is considering a little more difficult problem:
Given integers N and M, how many integer X satisfies 1<=X<=N and (X,N)>=M.
 

 

Input
The first line of input is an integer T(T<=100) representing the number of test cases. The following T lines each contains two numbers N and M (2<=N<=1000000000, 1<=M<=N), representing a test case.
 

 

Output
For each test case,output the answer on a single line.
 

 

Sample Input
3
1 1
10 2
10000 72
 

 

Sample Output
1
6
260
 

 

Source

 

题意概括:

求 1~N 的范围内存在多少个 X 使得 GCD( X, N ) >= M;

 

解题思路:

设 s = GCD( X, N);

可知: s >= M, 

且存在 a, b 使得 s*a = X, s*b = N, GCD( a, b ) = 1;

因为 X <= N 所以 a <= b;

综上所述:

N 1e9 的范围缩小一半枚举 s ,求得 b;(因为可以同时求得 i 和 N/i 的方案数)

即求满足 GCD(a, b) = 1 且 a <= b 的 a 的个数。

 

AC code:

 1 #include <bits/stdc++.h>
 2 #define INF 0x3f3f3f3f
 3 #define LL long long
 4 using namespace std;
 5 
 6 const int MAXN = 1e9+10;
 7 LL N, M;
 8 
 9 LL Euler(LL n)
10 {
11     LL res = n;
12     for(LL i = 2; i*i <= n; i++){
13         if(n%i == 0) res = res/i*(i-1);
14         while(n%i == 0) n/=i;
15     }
16     if(n > 1) res = res/n*(n-1);
17     return res;
18 }
19 
20 int main()
21 {
22     int T_case;
23     scanf("%d", &T_case);
24     LL ans, b;
25     while(T_case--){
26         scanf("%lld %lld", &N, &M);
27         ans = 0;
28         for(LL s = 1; s*s <= N; s++){
29             if(N%s) continue;
30             if(s >= M) ans+=Euler(N/s);
31             if(s*s != N && N/s >= M) ans+=Euler(s);
32         }
33         printf("%lld\n", ans);
34     }
35     return 0;
36 }
View Code

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值