HDU
来源:互联网 发布:linux apache安装目录 编辑:程序博客网 时间:2024/06/07 05:30
题目描述:
点击打开链接
题意给三个数m,n,k求第k个与m,n同时互质的数,lcm(m,n)的数据太大不好直接求然后循环找,那么就容斥了,这里涉及到一个小结论,即使是10^18级别的数据分解质因子也只会有二十几个不同的质因子而已,所以放心分解之后容斥,还有同样因为lcm(m,n)太大,所以最好分开分解然后set去重,最后也是因为lcm(m,n)太大,所以要二分找答案。
AC代码:
#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<cmath>#include<stack>#include<vector>#include<set>#include<queue>#include<algorithm>using namespace std;const int MAXM=25;long long gcd(long long x,long long y){ return y==0? x:gcd(y,x%y);}long long n,m,k;long long rec[33];long long handle(long long x,int cnt){ long long ans=0; long long k,p; for (int i=0;i<cnt;i++) { if (rec[i]>x) { cnt=i; break; } } for (int i=1;i<(1<<cnt);i++) { p=1; k=0; for (int j=0;j<cnt;j++) { if (i&(1<<j)) { k++; p=p*rec[j]; } } if (k&1) ans=ans+x/p; else ans=ans-x/p; } return ans;}int main(){ int T; scanf("%d",&T); int cas=1; while(T--) { cin>>n>>m>>k; long long tmpn=n; long long tmpm=m; set<long long > s1; for (int i=2;i*i<=n;i++) { if (tmpn%i==0) { s1.insert(i); while(tmpn%i==0) tmpn=tmpn/i; } } if (tmpn!=1) s1.insert(tmpn); for (int i=2;i*i<=m;i++) { if (tmpm%i==0) { s1.insert(i); while(tmpm%i==0) tmpm=tmpm/i; } } if (tmpm!=1) s1.insert(tmpm); int cnt=0; for (set<long long>::iterator it=s1.begin();it!=s1.end();it++) rec[cnt++]=*it; long long mid; long long L=0; long long R=0x3f3f3f3f3f3f3f3f; while(L<=R) { mid=(L+R)>>1; long long t=mid-handle(mid,cnt); if (t<k) L=mid+1; else R=mid-1; } printf("Case %d: %I64d\n",cas,L); cas++; } return 0;}