题意:
给定a和m,要求计算有多少个x(0 ≤ x < m),使 gcd(a, m) = gcd(a + x, m)
思路:
设g = gcd(a, m),gcd(a / g, m / g) = 1,令m' = m / g, a' = a / g,x' = x / g,则[a', a' + m') 中与m'互质的数量就是所求
由欧几里得性质知, gcd(a, b) = gcd(b * t + a, b),则 gcd(a - b, b) = gcd(a, b)
已知 a‘ ≤ a’ + x' < a‘ + m',得 0 ≤ (a’ + x’ ) % m‘ < m’ ,求出m‘的欧拉函数就是所求
Code:
#include <map> #include <set> #include <array> #include <queue> #include <stack> #include <vector> #include <cstdio> #include <cstring> #include <sstream> #include <iostream> #include <stdlib.h> #include <algorithm> #include <unordered_map> using namespace std; typedef long long ll; typedef pair<int, int> PII; #define sd(a) scanf("%d", &a) #define sdd(a, b) scanf("%d%d", &a, &b) #define slld(a) scanf("%lld", &a) #define slldd(a, b) scanf("%lld%lld", &a, &b) const int N = 100 + 10; const int M = 1e6 + 20; const int mod = 1e9 + 7; int t; ll a, m; ll get(ll n){ ll res = n; for(int 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() { #ifdef ONLINE_JUDGE #else // freopen("/home/jungu/code/in.txt", "r", stdin); #endif ios::sync_with_stdio(false); cin.tie(0), cout.tie(0); sd(t); while(t --){ slldd(a, m); m /= __gcd(a, m); cout << get(m) << " "; } return 0; }