poj2773(欧拉函数+二分+容斥)

欧几里得定理告诉我们gcd(n,m)==gcd(n,n-m),那么就有gcd(n,m)==gcd(n,n+m)

因此,对每n个数,与n取gcd的情况其实是相同的。。

然后可以利用欧拉函数把m的问题转化为在n内的问题。。

然后剩下的就是如何在1..n找第m个和n互斥的数了。。

直接枚举貌似可以过。。然而这样还要预处理欧拉函数干嘛。。所以肯定有更快的做法。。

找数肯定用二分查找比较优秀,关键是如何check。。

最主要还是找出1..t内有多少数和n互斥,其实对n分解质因数后就可以用容斥做了。。

考虑到质因子的平均个数为loglogn,所以复杂度为O(Tlog^2n+n)

 

 

/**
 *          ┏┓    ┏┓
 *          ┏┛┗━━━━━━━┛┗━━━┓
 *          ┃       ┃  
 *          ┃   ━    ┃
 *          ┃ >   < ┃
 *          ┃       ┃
 *          ┃... ⌒ ...  ┃
 *          ┃              ┃
 *          ┗━┓          ┏━┛
 *          ┃          ┃ Code is far away from bug with the animal protecting          
 *          ┃          ┃   神兽保佑,代码无bug
 *          ┃          ┃           
 *          ┃          ┃        
 *          ┃          ┃
 *          ┃          ┃           
 *          ┃          ┗━━━┓
 *          ┃              ┣┓
 *          ┃              ┏┛
 *          ┗┓┓┏━━━━━━━━┳┓┏┛
 *           ┃┫┫       ┃┫┫
 *           ┗┻┛       ┗┻┛
 */
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<set>
#include<bitset>
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)
#define link(x) for(edge *j=h[x];j;j=j->next)
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define eps 1e-8
#define succ(x) (1LL<<(x))
#define lowbit(x) (x&(-x))
#define sqr(x) ((x)*(x))
#define mid (x+y>>1)
#define NM 1000005
#define nm 200005
#define N 40005
#define M(x,y) x=max(x,y)
const double pi=acos(-1);
const int inf=1e9;
using namespace std;
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return f*x;
}


int n,m,c[NM],tot,phi[NM],prime[NM],_x,cnt,s;
bool v[NM];
ll ans;

void Euler(){
    n=1e6;phi[1]=1;
    inc(i,2,n){
	if(!v[i])prime[++tot]=i,phi[i]=i-1;
	inc(j,1,tot){
	    if(i*prime[j]>n)break;
	    v[i*prime[j]]++;
	    if(i%prime[j]==0){phi[i*prime[j]]=phi[i]*prime[j];break;}
	    phi[i*prime[j]]=phi[i]*(prime[j]-1);
	}
    }
}


void dfs(int i,int s,int t){
    if(s>_x)return;
    if(i==tot+1){if(s>1)cnt+=_x/s*(t&1?1:-1);return;}
    dfs(i+1,s,t);dfs(i+1,s*c[i],t+1);
}

bool check(int x){
    cnt=_x=x;dfs(1,1,1);
    return cnt<=m;
}

int main(){
    Euler();
    while(~scanf("%d%d",&n,&m)){
	ans=(ll)m/phi[n]*n;m%=phi[n];
	if(m==0)ans-=n,m=phi[n];
	int t=n;tot=0;
	inc(i,2,sqrt(t))if(t%i==0){
	    c[++tot]=i;
	    while(t%i==0)t/=i;
	}
	if(t>1)c[++tot]=t;
	for(int x=1,y=n;x<=y;)
	    if(check(mid))s=mid,x=mid+1;else y=mid-1;
	while(__gcd(s,n)>1)s--;
	ans+=s;
	printf("%lld\n",ans);
    }
    return 0;
}

 

 

 

Happy 2006

Time Limit: 3000MS Memory Limit: 65536K
Total Submissions: 14121 Accepted: 4995

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

Source

POJ Monthly--2006.03.26,static

[Submit]   [Go Back]   [Status]   [Discuss]

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值