標籤:des style blog class code tar
題目連結:
http://poj.org/problem?id=2773
Happy 2006
| Time Limit: 3000MS |
|
Memory Limit: 65536K |
| Total Submissions: 9131 |
|
Accepted: 3073 |
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 12006 22006 3 Sample Output 135 Source POJ Monthly--2006.03.26,static |
[Submit] [Go Back] [Status] [Discuss]
題目意思:
求與m互質的第k大的數
解題思路:
二分+容斥原理
二分出要求的數i,用容斥原理求出1~i之間的與m互質的數的個數kk,如果kk<k擴大範圍,如果kk>k擴大範圍,如果kk=k並且gcd(i,m)=1說明剛好找到,否則繼續縮小範圍。
代碼:
//#include<CSpreadSheet.h>#include<iostream>#include<cmath>#include<cstdio>#include<sstream>#include<cstdlib>#include<string>#include<string.h>#include<cstring>#include<algorithm>#include<vector>#include<map>#include<set>#include<stack>#include<list>#include<queue>#include<ctime>#include<bitset>#include<cmath>#define eps 1e-6#define INF 0x3f3f3f3f#define PI acos(-1.0)#define ll __int64#define LL long long#define lson l,m,(rt<<1)#define rson m+1,r,(rt<<1)|1#define M 1000000007//#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;#define N 1000bool isp[N+10];int pri[N+10],pp[N+10],cnt,cnt0;int m,k;ll res;void init() //打出1000內的質數{ cnt=0; for(int i=1;i<=N;i++) isp[i]=true; for(int i=2;i<=N;i++) { if(isp[i]) { pri[++cnt]=i; for(int j=i*2;j<=N;j+=i) isp[j]=false; } }}void Cal(int cur) //對cur分解質因數{ cnt0=0; for(int i=1;pri[i]*pri[i]<=cur;i++) { if(!(cur%pri[i])) { pp[++cnt0]=pri[i]; while(!(cur%pri[i])) cur/=pri[i]; } } if(cur!=1) pp[++cnt0]=cur;}void dfs(ll hav,int cur,int num,ll va) //容斥原理求出與m互質的且小於va的數的個數{ if(cur>cnt0||(hav>va)) return ; for(int i=cur;i<=cnt0;i++) { ll temp=hav*pp[i]; if(num&1) res-=va/temp; else res+=va/temp; dfs(temp,i+1,num+1,va); }}void solve(ll cur) //求出1~cur間與m互質的數的個數{ res=cur; for(int i=1;i<=cnt0;i++) { res-=cur/pp[i]; dfs(pp[i],i+1,2,cur); }}ll gcd(ll a,ll b) //求最大公約數{ if(a%b==0) return b; return gcd(b,a%b);}int main(){ //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); init(); while(~scanf("%d%d",&m,&k)) { ll ans,l,r,mid; l=1,r=(1LL<<62LL); //初始化一個很大的數 Cal(m); while(l<=r) { mid=(l+r)>>1; solve(mid); ll temp=res; //個數 //printf("mid:%I64d res:%I64d\n",mid,res); //system("pause"); if(temp<k) //放大 l=mid+1; else if(temp==k) { if(gcd(mid,m)==1) //最後一個剛好是與m互質的,說明恰好找到 { ans=mid; break; } r=mid-1; //否則繼續縮小 } else r=mid-1; } printf("%I64d\n",ans); } return 0;}