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;
}
// (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;
}
相关文章推荐
- HDU 1695 GCD (容斥 + 莫比乌斯反演)
- HDU 1695 GCD ( 容斥 + 欧拉 )
- Hdu 1695 GCD - 欧拉函数 + 容斥
- hdu 1695 GCD 欧拉函数 + 容斥
- HDU 1695 GCD(容斥原理、去重)
- hdu 1695 GCD (数论,容斥)
- HDU 1695-GCD(容斥)
- HDU 1695 GCD 容斥
- HDU 1695 GCD 容斥原理+欧拉
- Hdu 1695 - GCD (容斥)
- HDU 1695 GCD 【容斥】【质因数分解】【欧拉函数】
- hdu 1695 GCD 欧拉方程 容斥理论
- HDU 1695 GCD(容斥 or 莫比乌斯反演)
- HDU1695-GCD(数论-欧拉函数-容斥)
- HDU 1695 GCD(欧拉函数+容斥原理)
- GCD HDU - 1695 [Mobius]
- hdu 1695 GCD(莫比乌斯反演+分块模板)
- HDU 1695 GCD (欧拉函数+容斥原理)
- http://acm.hdu.edu.cn/showproblem.php?pid=3307 (欧拉 + 推导公式 + gcd)
- hdu 1695 GCD (欧拉函数、容斥原理)