3999 最大公约数(欧拉函数值)

1. 问题描述:

给定两个正整数 a,m,其中 a < m。请你计算,有多少个小于 m 的非负整数 x 满足:gcd(a,m) = gcd(a + x,m)

输入格式

第一行包含整数 T,表示共有 T 组测试数据。每组数据占一行,包含两个整数 a,m。

输出格式

每组数据输出一行结果,一个整数,表示满足条件的非负整数 x 的个数。

数据范围

前三个测试点满足,1 ≤ T ≤ 10。
所有测试点满足,1 ≤ T ≤ 50,1 ≤ a < m ≤ 1010。

输入样例:

3
4 9
5 10
42 9999999967

输出样例:

6
1
9999999966
来源:https://www.acwing.com/problem/content/4002/

2. 思路分析:

对于这种最大公约数的题目一般都需要推导一下,可以发现x也是d的倍数,其中d为a,m的最大公约数,令x' = x / d,m' = m / d,a' = a / d,所以(a' + x',m') = 1也即求解有多少个x'满足要求,0 <= x' < m,0 <= x' < m',也即求解a'~a' + m - 1中有多少个数与m'互质,通过下图可以发现求解的其实是0~m'之间有m'互质的数的个数,求解某个欧拉函数值可以使用公式在O(√n)的时间复杂度内求解出来。

下面的第一个公式是算数基本定理,第二个公式是N的欧拉函数计算公式,我们可以通过O(√n)的时间复杂度求解出N的欧拉函数值,

3. 代码如下:

class Solution:
    # 求解a和b的最大公约数
    def gcd(self, a: int, b: int):
        return a if b == 0 else self.gcd(b, a % b)

    # 求解m的欧拉函数值(使用公式求解即可)
    def phi(self, m: int):
        res = m
        i = 2
        while i * i <= m:
            if m % i == 0:
                res = res // i * (i - 1)
                # 将m中所有为i的因子除掉
                while m % i == 0:
                    m //= i
            i += 1
        # m > 1的时候也是一个质因子
        if m > 1:
            res = res // m * (m - 1)
        return res

    def process(self):
        T = int(input())
        for c in range(T):
            a, m = map(int, input().split())
            d = self.gcd(a, m)
            m //= d
            print(self.phi(m))


if __name__ == '__main__':
    Solution().process()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值