Same GCDs(欧拉函数)

题目链接:Same GCDs

大致题意

给定两个数n和m, 其中保证n < m.

问存在多少个整数x(0 ≤ x < m), 使得gcd(a, m) = gcd(a + x, m);

解题思路

本题是对欧拉函数的考察. 难点在于给定等式的变形.

首先因为a和m都是给定的, 所以不妨令常量 d = gcd(a, m) = gcd(a + x, m);

由于gcd(a, b) = gcd(b, a % b), 所以 gcd(a + x, m) = gcd((a + x) % m, m) = d

把**(a + x)记为x’, 因为x可以取[0, m), 而a ≥ 1, 因此(a + x) % m一定可以取遍[0, m), 因此x’ 可以取遍[0, m)**

<==> gcd(x’ % m / d, m / d) = 1 形式相当于 gcd(x’ % n, n). 同理得出x’ % n一定可以取遍[0, n).

由于欧拉函数的定义是求[1, n]之中, 所有与n互质的数的个数, 而本题所得到的区间是[0, n), 需要进一步转换.

首先当x’ % n == 0时, 是没有意义的, 区间可以变为[1, n).
此时若n == 1, 那么区间应当变为[1, 1], 若n != 1, 那么n与其自身一定不互质, 则区间可以变为[1, n].

综上所述, 可以用欧拉函数来计算上式成立的次数, 相当于得到x的可取值个数.

AC代码

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll fact(ll n) { //求单个数欧拉函数模板, 复杂度O(√n)
    ll res = n;
    for (ll i = 2; i <= n / i; ++i) {
        if (n % i == 0) {
            res = res / i * (i - 1);
            while (n % i == 0) n /= i;
        }
    }
    if (n > 1) res = res / n * (n - 1);
    return res;
}
int main()
{
    int t; cin >> t;
    while (t--) {
        ll a, m; cin >> a >> m;
        ll d = gcd(a, m);
        ll res = fact(m / d);
        printf("%lld\n", res);
    }
    return 0;
}

菜鸡不会数论, 我乱讲的, 如果有地方说的不对麻烦评论直接指出.

END

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逍遥Fau

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值