poj 2773 Happy 2016
题意:
给定$m, k$,找第$k$大与$m$互质的数
思路:
根据 $gcd(a, b) = gcd(b * t + a, b) $ (t 为任意整数)
则如果$a$与$b$互素,$b * t + a$ 与 $b$ 也互素,否则 $b * t + a$ 与 $b$ 不互素,故与$m$互素的数对$m$取模具有周期性。
假设小于$m$的数且与$m$互素的数有$k$个,第$i$个为$a_i$,则第$n * k + i$个与 $m$互素的数是$n * m + a_i$
Code:
#pragma GCC optimize(3) #pragma GCC optimize(2) #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 Time (double)clock() / CLOCKS_PER_SEC #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 = 1e6 + 20; const int M = 1e6 + 20; const int mod = 1e9 + 7; int n, m, k; int primes[N], cnt, phi[N]; bool st[N]; void get_eulers(int n) { phi[1] = 1; for (int i = 2; i <= n; i++) { if (!st[i]) { primes[cnt++] = i; phi[i] = i - 1; } for (int j = 0; primes[j] <= n / i; j++) { st[i * primes[j]] = true; if (i % primes[j] == 0) { phi[i * primes[j]] = primes[j] * phi[i]; break; } phi[i * primes[j]] = (primes[j] - 1) * phi[i]; } } } void solve() { get_eulers(N - 20); while (~sdd(m, k)) { n = k / phi[m]; k %= phi[m]; if (k == 0) { k = phi[m]; n--; } for (int i = 1; i <= m; i++) { if (__gcd(i, m) == 1) { k--; } if (!k) { cout << n * m + i << "\n"; break; } } } } int main() { #ifdef ONLINE_JUDGE #else freopen("/home/jungu/code/in.txt", "r", stdin); // freopen("/home/jungu/code/out.txt", "w", stdout); // freopen("/home/jungu/code/out.txt","w",stdout); #endif // ios::sync_with_stdio(false); cin.tie(0), cout.tie(0); int T = 1; // sd(T); while (T--) { solve(); } return 0; }