当前位置 : 主页 > 编程语言 > java >

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

来源:互联网 收集:自由互联 发布时间:2022-09-02
欧几里得定理告诉我们gcd(n,m)==gcd(n,n-m),那么就有gcd(n,m)==gcd(n,n+m) 因此,对每n个数,与n取gcd的情况其实是相同的。。 然后可以利用欧拉函数把m的问题转化为在n内的问题。。 然后剩下


欧几里得定理告诉我们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

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

Time Limit: 3000MS

 

Memory Limit: 65536K

Total Submissions: 14121

 

Accepted: 4995

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

 

 

上一篇:poj1456(贪心+优先队列)
下一篇:没有了
网友评论