#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MID(x,y) ((x+y)>>1)
using namespace std;
typedef long long LL; //max long long == 9223372036854775807LL
LL phi(LL n)
{
if (n == 1) return 0;
LL i,sum=n;
for(i=2; i*i<=n; i++)
{
if(n%i==0)
{
sum = sum / i * (i-1);
do
{
n/=i;
}
while(n%i==0);
}
}
if(n>1) sum = sum / n * (n - 1);
return sum;
}
int solve(int r, int n){
if (r == 0) return 0;
int res = 0;
vector p;
for (int i = 2; i * i <= n; i ++){
if (n % i == 0){
p.push_back(i);
while(n % i == 0){
n /= i;
}
}
if (n == 1) break;
}
if (n > 1) p.push_back(n);
for (int msk = 1; msk < (1 << p.size()); msk ++){
int mult = 1, bit = 0;
for (int i = 0; i < p.size(); i ++){
if (msk & (1 << i)){
bit ++;
mult *= p[i];
}
}
int cur = r / mult;
if (bit % 2 == 1){
res += cur;
}
else{
res -= cur;
}
}
return r - res;
}
int main(){
int t, caseo = 1;
cin>>t;
while(t --){
int a,b,c,d,k;
cin>>a>>b>>c>>d>>k;
if (k == 0){
cout< d){
int tmp = d;
d = b;
b = tmp;
}
LL ans = 0;
for (int i = 1; i <= b; i ++){
ans += (LL)solve(d, i) - phi(i);
}
cout<
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=1695
题目大意:求[1..b]中的x和[1..d]中的y有多少gcd(x,y) = k.
思路: 预备知识:
容斥原理求数区间[1..r]中与n互质的数的个数.
Here 要求gcd(x,y) = k,则等价于求 gcd(x/k,y/k) = 1.所以问题转化成求[1..b/k]和[1..d/k]中有多少对gcd(x,y) = 1. 又因为此题要求gcd(1,3)和gcd(3,1)算一个,所以我们不妨按x < y来求. 接下来,我们枚举x的值,然后便转化为求[x..d/k]区间中与x互质的数的个数,用容斥原理解决. [x..d/k] = [1..d/k] - [1..x-1],[1..d/k]我们用上面的容斥原理方法就可以解决,[1..x-1]虽然也可以用容斥,但速度较慢,明显可以用更快的欧拉函数做。
转载于:https://www.cnblogs.com/AbandonZHANG/archive/2012/12/02/4114183.html