【刷题】HDU 1695 GCD

Problem Description

Given 5 integers: a, b, c, d, k, you're to find x in a...b, y in c...d that GCD(x, y) = k. GCD(x, y) means the greatest common divisor of x and y. Since the number of choices may be very large, you're only required to output the total number of different number pairs.
Please notice that, (x=5, y=7) and (x=7, y=5) are considered to be the same.

Yoiu can assume that a = c = 1 in all test cases.

Input

The input consists of several test cases. The first line of the input is the number of the cases. There are no more than 3,000 cases.
Each case contains five integers: a, b, c, d, k, 0 < a <= b <= 100,000, 0 < c <= d <= 100,000, 0 <= k <= 100,000, as described above.

Output

For each test case, print the number of choices. Use the format in the example.

Sample Input

2
1 3 1 5 1
1 11014 1 14409 9

Sample Output

Case 1: 9
Case 2: 736427

Hint
For the first sample input, all the 9 pairs of numbers are (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 5), (3, 4), (3, 5).

Description(CHN)

(sum_{i=1}^bsum_{j=1}^d[gcd(i,j)=k])

Solution

水一道题,随便莫反一下就好了
(f(d)=sum_{i=1}^nsum_{j=1}^m[gcd(i,j)=d])
(F(d)=sum_{i=1}^nsum_{j=1}^m[d|gcd(i,j)]=lfloor frac{n}{d} floor lfloor frac{m}{d} floor=sum_{d|n}f(n))
所以 (f(d)=sum_{d|p}mu(frac{p}{d})F(p)=sum_{t=1}^{frac{min(n,m)}{d}}mu(t)F(dt)=sum_{t=1}^{frac{min(n,m)}{d}}mu(t)lfloor frac{n}{dt} floor lfloor frac{m}{dt} floor)
最后, (ans=f(1)=sum_{t=1}^{min(n,m)}mu(t)lfloor frac{n}{t} floor lfloor frac{m}{t} floor)
整除分块算(似乎都不需要整除分块?
哦,对于无序对的处理,发现无序对的重复只存在于 (i<=min(n,m),j<=min(n,m)) 的情况下,否则一方将达不到另一方的数
那么算出总的,减去这个 (min) 的答案除二的商,就是最后的结果了(体会体会)

#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
const int MAXN=100000+10;
int T,vis[MAXN],prime[MAXN],cnt,mu[MAXN],s[MAXN],a,b,c,d,k;
ll ans;
template<typename T> inline void read(T &x)
{
	T data=0,w=1;
	char ch=0;
	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
	if(ch=='-')w=-1,ch=getchar();
	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
	x=data*w;
}
template<typename T> inline void write(T x,char ch='')
{
	if(x<0)putchar('-'),x=-x;
	if(x>9)write(x/10);
	putchar(x%10+'0');
	if(ch!='')putchar(ch);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline void init()
{
	memset(vis,1,sizeof(vis));
	vis[0]=vis[1]=0;
	mu[1]=1;
	for(register int i=2;i<MAXN;++i)
	{
		if(vis[i])
		{
			prime[++cnt]=i;
			mu[i]=-1;
		}
		for(register int j=1;j<=cnt&&i*prime[j]<MAXN;++j)
		{
			vis[i*prime[j]]=0;
			if(i%prime[j])mu[i*prime[j]]=-mu[i];
			else break;
		}
	}
	for(register int i=1;i<MAXN;++i)s[i]=s[i-1]+mu[i];
}
inline ll solve(int n,int m)
{
	ll res=0;
	for(register int i=1;;)
	{
		if(i>min(n,m))break;
		int j=min(n/(n/i),m/(m/i));
		res+=1ll*(n/i)*(m/i)*(s[j]-s[i-1]);
		i=j+1;
	}
	return res;
}
int main()
{
	init();
	read(T);
	for(register int i=1;i<=T;++i)
	{
		printf("Case %d: ",i);
		read(a);read(b);read(c);read(d);read(k);
		if(!k)
		{
			puts("0");
			continue;
		}
		b/=k;d/=k;
		write(solve(b,d)-(solve(min(b,d),min(b,d))>>1),'
');
	}
	return 0;
}
原文地址:https://www.cnblogs.com/hongyj/p/9302072.html