您的位置:首页 > 其它

hdu 1695 GCD 容斥+欧拉

2016-10-16 11:24 375 查看
//求(x,y)=k有多少个 x为1~a y为1~b

// (x/k,y/k)=1 即x=kp y=kq有多少个与q互质的p就有多少个x满足

//较大数为y时 则当y<=a时 符合条件的x的个数即为phi[1]+..phi[a/k]

// a+1<=y<=b时 另一个数x不能大于a 则x<=a&&与y互质的个数为 (a-不与y互质的个数)

//不与y互质 则含有y某些个素因子的倍数 y=p1^a1*..pn^an 则与y不互质的为集合(p1Up2U..pn) 

#include <iostream>
#include <cstring>
#include <vector>
#include <cmath>
#include <map>
using namespace std;
const int N=1e6+20;
typedef long long ll;
long long a,b;
int phi[N+20];
//求(x,y)=k有多少个 x为1~a y为1~b
// (x/k,y/k)=1 即x=kp y=kq有多少个与q互质的p就有多少个x满足
//较大数为y时 则当y<=a时 符合条件的x的个数即为phi[1]+..phi[a/k]

// a+1<=y<=b时 另一个数x不能大于a 则x<=a&&与y互质的个数为 (a-不与y互质的个数)
//不与y互质 则含有y某些个素因子的倍数 y=p1^a1*..pn^an 则与y不互质的为集合(p1Up2U..pn)
void Euler()
{
for(int i=2;i<=N;i++)
phi[i]=i;

phi[1]=1;
for(int i=2;i<=N;i++)
{
if(phi[i]==i)//素因子i
{
phi[i]=i-1;
for(int j=i+i;j<=N;j+=i)
{
phi[j]=phi[j]/i*(i-1);
}
}
}

}
int Inclusion(int a,int n)
{
int res=0;
int cnt=0;//素因子个数
int fac[10];//n<=1e5 素因子个数不会超过10个
if(n==1)
return 0;
for(int i=2;i<=sqrt(n+0.5);i++)
{
if(n%i==0)
fac[cnt++]=i;
while(n%i==0)
n/=i;
}
if(n>1)//大于sqrt(n)的素数
fac[cnt++]=n;

for(int i=1;i< (1<<cnt);i++)//枚举选取的集合
{
int mul=1;//乘积
int cur=i;//
int j=0;//当前是第几位
int tmp=0;//有几位1
while(cur)
{
if(cur&1)
{
tmp++;
mul*=fac[j];
}
j++;
cur>>=1;
}
if(tmp%2)//容斥:奇数个为+
{
res+=a/mul;
}
else
{
res-=a/mul;
}
}
return res;
}
int main()
{
int t;
cin>>t;
Euler();
for(int cas=1;cas<=t;cas++)
{
ll ans=0;
int c,a,b,k;
cin>>c>>a>>c>>b>>k;
if(k==0)
{
ans=0;
printf("Case %d: %lld\n",cas,ans);
continue;
}
a/=k;
b/=k;
if(a>b)
swap(a,b);

for(int y=1;y<=a;y++)
{
ans+=phi[y];//较大的<=a时
}
for(int y=a+1;y<=b;y++)
{
ans+=a-Inclusion(a,y);//利用容斥原理求不互质的个数(素因子集合的并集)
}
printf("Case %d: %lld\n",cas,ans);

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