hdu 1695 GCD 容斥+欧拉

//求(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;  
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值