您的位置:首页 > 移动开发

POJ 2773 Happy 2006 [容斥原理]

2016-07-24 17:30 423 查看
Happy 2006

Time Limit: 3000MS Memory Limit: 65536KB 64bit IO Format: %lld & %llu

Description

Two positive integers are said to be relatively prime to each other if the Great Common Divisor (GCD) is 1. For instance, 1, 3, 5, 7, 9…are all relatively prime to 2006.

Now your job is easy: for the given integer m, find the K-th element which is relatively prime to m when these elements are sorted in ascending order.

Input

The input contains multiple test cases. For each test case, it contains two integers m (1 <= m <= 1000000), K (1 <= K <= 100000000).

Output

Output the K-th element in a single line.

Sample Input

2006 1

2006 2

2006 3

Sample Output

1

3

5

一句话,就是求第k个与m互质的数

由于互质的数与范围不一样,那么只能回到欧拉定理的上一步容斥原理

那么考虑给一个确定的范围,范围越大,其中互质的数越多,答案就具有单调性,考虑二分!

单次求互质的数的个数,用容斥原理,减去所有不互质的个数就是互质的了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<iomanip>
#include<ctime>
#include<climits>
#include<cctype>
#include<algorithm>
#ifdef WIN32
#define AUTO "%I64d"
#else
#define AUTO "%lld"
#endif
using namespace std;
#define smax(x,tmp) x=max((x),(tmp))
#define smin(x,tmp) x=min((x),(tmp))
#define maxx(x1,x2,x3) max(max(x1,x2),x3)
#define minn(x1,x2,x3) min(min(x1,x2),x3)
typedef long long LL;
const int INF=0x3f3f3f3f;
const int maxn = 1005;
int p[maxn];
int cnt;
int m,k;
inline bool init()
{
if(!~scanf("%d%d",&m,&k)) return false;
memset(p,0,sizeof(p));cnt = 0; // initialize totally here!!
int tmp = m;
for(int i=2;i*i<=tmp;i++)
{
if(m == m/i*i) p[++cnt] = i;
while(m%i == 0) m /= i;
}
if(m > 1) p[++cnt] = m;
return true;
}
LL f(LL x) // cnt of the relatively prime less than x
{
LL res = 0ll;
for(int status=1;status ^ (1<<cnt);status++)
{
int tot=0;
LL pie = 1ll;
for(int i=0;i<cnt;i++) if(status & (1<<i))
{
tot++;
pie *= p[i+1];
}
if(tot&1) res -= x/pie;
else res += x/pie;
}
return x + res;
}
LL in_ex()
{
LL l = 1ll , r = (1ll<<38); // set the primes are from 2 to 19, relatively equals to 1e7(maxm), limitly use phi(2 to 19) = 1e9(maxk) / 0.17... = 1e10
while(l<r)
{
LL m = (l+r)>>1;
LL cur = f(m);
if(cur < k) l = m+1;
else r = m; // if == , continue to find the left element that suits the query and decrease 1 to find the ans
}
return l;
}
int main()
{
freopen("happy.in","r",stdin);
freopen("happy.out","w",stdout);
while(init())
{
LL ans = in_ex();
printf(AUTO"\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息