hdu1695 GCD

时间:2021-11-03 02:36:06
  http://acm.hdu.edu.cn/showproblem.php?pid=1695
1 /**
大意: a<=x<=b , c<= y <= d ,求在此范围内 有多少组x,y 满足 gcd(x,y) = k ; a=c=1(题目有问题)gcd(x,y),gcd(y,x) 算一个
思路: 也就是求 1 - - b/k, 1 -- d/k 内有多少个数互素,
1、 若k =0, 则 res =0, 因为任何两个数的gcd 不可能为 0
2、 若k !=0 , 设b = b/k, d = d/k, 默认 d>b 那么
对于1-b 之间的互质的数 就是欧拉函数,
对于b+1 -- d 从b+1 -- d 之间找一个数y, 在 1 - b 之间寻找与其互质的数。 那么 1 -b 之间的数 肯定不含有y的质因子, 那么将y 质因数分解, 在 1 -- b 之间的数,中除掉 含有 y因子的数(注意这里不只是质因子,是y所有的因子)。。 剩下的即为所求。。
---------------------------------------------------------------------------------
别人的解释
求[1..b]中的x和[1..d]中的y有多少gcd(x,y) = k.
要求gcd(x,y) = k,则等价于求 gcd(x/k,y/k) = 1.所以问题转化成求[1..b/k]和[1..d/k]中有多少对gcd(x,y) = 1. 进一步转换成 枚举[1,d]区间里的n与][1, b]的区间的数互质的个数,这里d>=b.
因为[1,b]包含在[1,d]里,所以[1,b]相当于累加欧拉函数phi(i)的值,而[b + 1, d]这个区间可以通过容斥原理来求出.
要求n与][1, b]的区间的数互质的个数,可以考虑求与n不互质数的个数v, 那么互质的数自然就是b - v.
所以分解n的素因子,考虑n的素因子pi,则[1, b]中与pi不互质的数的个数是[b/pi](即其multiples).
如果这样累加[b/pi]的话则会加上很多重复的值(一个数可能有多个素因子),这里容斥原理就派上用场了.
------------------------------------------------------------------------------------- **/ #include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
const long long maxn = ;
long long phi[maxn];
long long priD[maxn];
long long len; void euler(long long n){
len =;
long long m = (long long )sqrt(n+0.5);
for(int i=;i<=m;i++) if(n%i==){
priD[len++] = i;
while(n%i==)
n = n/i;
}
if(n>)
priD[len++] = n;
} void phi_table(){
for(int i=;i<maxn;i++)
phi[i] =;
phi[] =;
for(int i=;i<maxn;i++)if(!phi[i]){
for(int j=i;j<maxn;j+=i){
if(!phi[j]) phi[j] =j;
phi[j] = phi[j] /i *(i-);
}
}
} long long solve(long long n){
long long sum =;
for(long long i=;i<1ll<<len;i++){
long long tmp =;
long long flag =;
for(int j =;j<len;j++){
if(i&(1ll<<j)){
flag ++;
tmp *= priD[j];
}
}
if(flag%)
sum += n/tmp;
else
sum -= n/tmp;
}
return sum;
} int main()
{
phi_table();
int t;
cin>>t;
int cnt;
long long a,b,c,d,k;
for(cnt =;cnt<=t;cnt++){
cin>>a>>b>>c>>d>>k;
if(k==){
cout<<"Case "<<cnt<<": "<<<<endl;
continue;
}
b = b/k;
d = d/k;
if(b>d){
swap(b,d);
}
long long res =;
for(int i=;i<=b;i++)
res += phi[i];
for(int i=b+;i<=d;i++){
euler(i);
res += (b - solve(b));
}
cout<<"Case "<<cnt<<": "<<res<<endl;
}
return ;
}