HDU题目链接
求第k个与n,m都互素的正数(0 < m, n, k <= 10^9)
使用二分法查找元素
二分0~(1LL<
用容斥原理求[1,x]中可以被几个数整除的数的个数
long long prime[MAXN], tot;
long long check[MAXN];
void eular(){
memset(check, 0, sizeof(check));
tot = 0;
for(int i = 2; i<MAXN; i++){
if(!check[i])
prime[tot++] = i;
for(int j = 0; j<tot && prime[j]*i<MAXN; j++){
check[i*prime[j]] = 1;//素数的倍数为合数
if(i%prime[j] == 0) break;
}
}
}
for(long long i = 0;prime[i]*prime[i] <=m; i++){
if(m%prime[i] == 0){
fac[cnt1++] = prime[i];
while(m%prime[i] == 0) m/=prime[i];
}
}
if(m > 1) fac[cnt1++] = m;
long long RC(long long x){
long long ret = 0, tmp, cnt;
for(long long i = 1; i<(1LL<<cnt1); i++){
tmp = 1, cnt = 0;
for(long long j = 0; j<cnt1; j++){
if(i&(1LL<<j)){
tmp *=fac[j];
cnt++;
}
}
if(cnt&1) ret += x/tmp;
else ret -= x/tmp;
}
return ret;
}
#include
using namespace std;
#define MAXN 1000005
long long fac[MAXN], cnt1;
long long prime[MAXN], tot;
long long check[MAXN];
long long n, m, k;
void eular(){
memset(check, 0, sizeof(check));
int tot = 0;
for(int i = 2; i<MAXN; i++){
if(!check[i])
prime[tot++] = i;
for(int j = 0; j<tot && prime[j]*i<MAXN; j++){
check[i*prime[j]] = 1;//素数的倍数为合数
if(i%prime[j] == 0) break;
}
}
}
void getFac(long long n, long long m){
cnt1 = 0;
for(long long i = 0;prime[i]*prime[i] <=n; i++){
if(n%prime[i] == 0){
fac[cnt1++] = prime[i];
while(n%prime[i] == 0) n/=prime[i];
}
}
if(n > 1) fac[cnt1++] = n;
for(long long i = 0;prime[i]*prime[i] <=m; i++){
if(m%prime[i] == 0){
fac[cnt1++] = prime[i];
while(m%prime[i] == 0) m/=prime[i];
}
}
if(m > 1) fac[cnt1++] = m;
sort(fac, fac+cnt1);
int tmp = unique(fac, fac+cnt1) - fac;
cnt1 = tmp;
}
//状态压缩所有的因子组合,[1,x]中不是互素的数有x/因子*因子,容斥原理排除重复
long long RC(long long x){
long long ret = 0, tmp, cnt;
for(long long i = 1; i<(1LL<<cnt1); i++){
tmp = 1, cnt = 0;
for(long long j = 0; j<cnt1; j++){
if(i&(1LL<<j)){
tmp *=fac[j];
cnt++;
}
}
if(cnt&1) ret += x/tmp;
else ret -= x/tmp;
}
return ret;
}
long long DS(){
long long l = 0, r = (1LL<<62), mid, ans;
while(l <= r){
mid = (l+r) / 2;
if(mid - RC(mid) >= k){
ans = mid;
r = mid - 1;
}else{
l = mid + 1;
}
}
return ans;
}
int main(int argc, char const *argv[])
{
eular();
int t;scanf("%d", &t);
for(int cnt = 1; cnt<=t; cnt++){
scanf("%lld%lld%lld", &m, &n, &k);
getFac(m, n);
printf("Case %d: %lld\n", cnt,DS());
}
return 0;
}