题目来源: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;
}