Codeforces - 920G - List Of Integers
题意是求大于x且与p互质的第k个数。
不大于num且与p互质的数的个数=num-不大于num且与p有公因子的数的个数,这样就可以用容斥求了:如p有素因子ABC
有公因子A的个数+有公因子B的个数+有公因子C的个数-有公因子AB-有公因子BC-有公因子AC+有公因子ABC
由于p最多有7个公因子,容斥的复杂度是 O(7∗27) O ( 7 ∗ 2 7 ) 。分解素因子的复杂度是 1000 1000 ,因此就可以高了。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int x,k,p;
vector<ll> fac;
void getfac()
{
fac.clear();
int tmp = p;
for(int i=2;i*i<=tmp;++i)
{
if(tmp%i==0)
{
fac.push_back(i);
while(tmp%i==0) tmp/=i;
}
}
if(tmp!=1) fac.push_back(tmp);
}
int check(ll num)
{
//不大于num且与p互质的数=num-与p有相同因子的数
//与p有相同因子(ABC)的数=A+B+C-AB-AC-BC+ABC ...
ll res=0;
int c=1;
int sz=fac.size();
for(int i=1;i<(1<<sz);++i)
{
int v = __builtin_popcount(i);
ll mul = 1;
for(int j=0;j<sz;++j)
if((i>>j)&1) mul*=fac[j];
res += ((v&1)?1:-1)*(num/mul-x/mul);
}
res = num-x-res;
return res;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&x,&p,&k);
int l=x+1,r=1e9;
getfac();
while(l<r)
{
int m=(l+r)>>1;
if(check(m)<k) l=m+1;
else r=m;
}
printf("%d\n",r);
}
return 0;
}