您的位置:首页 > 其它

容斥原理应用(求1~r中有多少个数与n互素)

2013-08-10 19:29 281 查看


容斥原理应用(求1~r中有多少个数与n互素)

分类: 数论2013-08-02
20:15 121人阅读 评论(0) 收藏 举报

问题:求1~r中有多少个数与n互素。

对于这个问题由容斥原理,我们有3种写法,其实效率差不多。分别是:dfs,队列数组,位运算。

先说说位运算吧:

用二进制1,0来表示第几个素因子是否被用到,如m=3,三个因子是2,3,5,则i=3时二进制是011,表示第2、3个因子被用到

[cpp] view
plaincopy

LL Solve(LL n,LL r)

{

vector<LL> p;

for(LL i=2; i*i<=n; i++)

{

if(n%i==0)

{

p.push_back(i);

while(n%i==0) n/=i;

}

}

if(n>1)

p.push_back(n);

LL ans=0;

for(LL msk=1; msk<(1<<p.size()); msk++)

{

LL multi=1,bits=0;

for(LL i=0; i<p.size(); i++)

{

if(msk&(1<<i)) //判断第几个因子目前被用到

{

++bits;

multi*=p[i];

}

}

LL cur=r/multi;

if(bits&1) ans+=cur;

else ans-=cur;

}

return r-ans;

}

然后就是dfs的实现:

[cpp] view
plaincopy

void Solve(LL n)

{

p.clear();

for(LL i=2; i*i<=n; i++)

{

if(n%i==0)

{

p.push_back(i);

while(n%i==0) n/=i;

}

}

if(n>1)

p.push_back(n);

}

void dfs(LL k,LL t,LL s,LL n)

{

if(k==p.size())

{

if(t&1) ans-=n/s;

else ans+=n/s;

return;

}

dfs(k+1,t,s,n);

dfs(k+1,t+1,s*p[k],n);

}

//主函数内是:

df


HDU3388(二分+容斥原理)

分类: 组合博弈2013-08-04
11:49 20人阅读 评论(0) 收藏 举报

题目:Coprime

题意:给三个数m,n,k, 0<m,n,k<10^9,求与m,n同时互质的第k个正整数(按从小到达顺序排列).

思路:二分+容斥原理

由于所找的数与m,n互质,那么这个数不能含有m,n所包含的素因子。但是k很大,不可能一个一个生成。于是二分,找到最小

的x,使得小于或等于x的数中满足条件的数的个数大于或等于k,则这个最小值即为答案。

在判断小于或等于x的数中满足条件的数的个数时,可用容斥原理找出这些数中是m,n所含质因子倍数的数的个数。x减去所得

个数即为小于或等于x的数中满足条件的数的个数。

[cpp] view
plaincopy

#include <iostream>

#include <string.h>

#include <algorithm>

#include <stdio.h>

using namespace std;

typedef long long LL;

const int N=1000005;

const LL INF=(LL)1<<62;

bool prime
;

LL p
;

LL fac
;

LL k,cnt,num,ans,n,m,K;

void isprime()

{

k=0;

int i,j;

memset(prime,true,sizeof(prime));

for(i=2; i<N; i++)

{

if(prime[i])

{

p[k++]=i;

for(j=i+i; j<N; j+=i)

{

prime[j]=false;

}

}

}

}

void Solve(LL m,LL n)

{

cnt=0;

LL i;

for(i=0; p[i]*p[i]<=n; i++)

{

if(n%p[i]==0)

{

fac[cnt++]=p[i];

while(n%p[i]==0) n/=p[i];

}

}

if(n>1)

fac[cnt++]=n;

for(i=0; p[i]*p[i]<=m; i++)

{

if(m%p[i]==0)

{

fac[cnt++]=p[i];

while(m%p[i]==0) m/=p[i];

}

}

if(m>1)

fac[cnt++]=m;

}

void dfs(LL k,LL t,LL s,LL n)

{

if(k==num)

{

if(t&1) ans-=n/s;

else ans+=n/s;

return;

}

dfs(k+1,t,s,n);

dfs(k+1,t+1,s*fac[k],n);

}

LL Binary()

{

LL l=1,r=INF,mid,ret;

while(l<=r)

{

mid=(l+r)/2;

ans=0;

dfs(0,0,1,mid);

if(ans>=K)

{

ret=mid;

r=mid-1;

}

else

l=mid+1;

}

return ret;

}

int main()

{

isprime();

LL t,ct,tt=1;

scanf("%I64d",&t);

while(t--)

{

scanf("%I64d%I64d%I64d",&m,&n,&K);

printf("Case %d: ",tt++);

if(n==1&&m==1)

{

printf("%I64d\n",k);

continue;

}

Solve(m,n);

sort(fac,fac+cnt);

num=1;

for(LL i=1; i<cnt; i++)

{

if(fac[i]!=fac[i-1])

{

fac[num++]=fac[i];

}

}

ct=num;

printf("%I64d\n",Binary());

}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: