[HDU1695]GCD

[HDU1695]GCD

标签: 莫比乌斯反演


题目链接

题解

裸的莫比乌斯反演啊。
考虑重复的情况,我们直接减去相交区间(较小区间)内答案的二分之一。
刚好加上了gcd(k,k)==k的情况。

Code

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std;
#define ll long long
#define REP(i,a,b) for(int i=(a),_end_=(b);i<=_end_;i++)
#define DREP(i,a,b) for(int i=(a),_end_=(b);i>=_end_;i--)
#define EREP(i,a) for(int i=start[(a)];i;i=e[i].next)
inline int read()
{
	int sum=0,p=1;char ch=getchar();
	while(!(('0'<=ch && ch<='9') || ch=='-'))ch=getchar();
	if(ch=='-')p=-1,ch=getchar();
	while('0'<=ch && ch<='9')sum=sum*10+ch-48,ch=getchar();
	return sum*p;
}

const int maxn=1e5+20;

int prime[maxn],mark[maxn],tot,mu[maxn];

inline void prepare()
{
	mu[1]=1;
	REP(i,2,100000)
	{
		if(!mark[i])
		{
			prime[++tot]=i;
			mu[i]=-1;
		}
		for(int j=1;j<=tot && prime[j]*i<=maxn;j++)
		{
			mark[i*prime[j]]=1;
			if(i%prime[j])mu[i*prime[j]]=-mu[i];
			else {mu[i*prime[j]]=0;break;}
		}
	}
}

int a,b,c,d,k;

inline void init()
{
	a=read();b=read();c=read();d=read();k=read();
	if(b<d)swap(b,d);
}

void doing(int Case)
{
	ll ans1=0;
	ll ans2=0;
	if(k==0)
	{
		printf("Case %d: %lld\n",Case,0ll);
		return;
	}
	for(int i=k;i<=b;i+=k)ans1+=(ll)(b/i)*(d/i)*mu[i/k];
	for(int i=k;i<=d;i+=k)ans2+=(ll)(d/i)*(d/i)*mu[i/k];
	printf("Case %d: %lld\n",Case,ans1-ans2/2);
}

int main()
{
	prepare();
	int t=read(),Case=0;
	while(t--)
	{
		++Case;
		init();
		doing(Case);
	}
	return 0;
}
posted @ 2017-10-20 22:23  Deadecho  阅读(138)  评论(0编辑  收藏  举报