题目来源:http://poj.org/problem?id=2773
勉强过!
#include <cstdio> #include <cstring> #include <iostream> using namespace std; typedef long long LL; const int MAXN = 1000010; //如果求,x, y的公约数,如果x = k*x1, y = k*y1,则:Gcd(x, y) = k*Gcd(x1, y1); //如果x = p*x1, 其中p为素数,并且y%p != 0, 则:Gcd(x, y) = Gcd(p*x1, y1) = Gcd(x1, y); int Revise_Gcd(int a, int b)//求公约数,这个效率最高 { if(a < b) return Revise_Gcd(b, a); if(b == 0) return a; else { if(!(a & 1)) { if(!(b & 1)) return (Revise_Gcd(a >> 1, b >> 1)<<1); else return Revise_Gcd(a >> 1, b); } else { if(!(b&1)) return Revise_Gcd(a, b >> 1); else return Revise_Gcd(b, a-b); } } } int main() { int m, k, i, num; int IsPrime[MAXN]; while(~scanf("%d %d", &m, &k)) { if(m == 1) { printf("%d\n", k); continue ; } num = 0; for(i = 1; i < m; ++i) if(Revise_Gcd(i, m) == 1) IsPrime[num++] = i; k--; printf("%lld\n", k/num*(LL)m + IsPrime[k%num]); } return 0; }
方法二,容斥原理+二分,非常之快!
//利用二分计算[1, 2^64]中每个x的因子不与m互素的个数y,那么x-y == k时,x就是答案 #include <iostream> #include <cstring> #include <cstdio> using namespace std; const int MAXN = 1000010; typedef __int64 LL; int NotPrime[MAXN], num; void Inite(int n) { int i; num = 0; for (i = 2; i * i <= n; ++i) { if(n%i == 0) NotPrime[num++] = i; while(n%i == 0) n /= i; } if(n != 1) NotPrime[num++] = n; } LL Binary_Search_Ans( LL n ) { int i, j; LL tmp, sum, res = 0, k; for (i = 1; i < (1<<num); ++i)//容斥原理的模版 { tmp = 0, sum = 1; for (j = 0; j < num; ++j) { if(i & (1<<j)) tmp++, sum *= NotPrime[j]; } k = n/sum; if(tmp & 1) res -= k; else res += k; } return n + res; } int main() { int m, k; LL iLeft, iRight, iMid, tmp; while (~scanf("%d %d", &m, &k)) { Inite(m); iLeft = 1, iRight = (1LL << 60); while (iLeft < iRight) { iMid = (iLeft + iRight)>>1; tmp = Binary_Search_Ans(iMid) ; if (tmp >= k) iRight = iMid; else iLeft = iMid + 1; } printf("%I64d\n", iLeft); } return 0; }