洛谷P3455

题目链接

(Solution:)

莫比乌斯反演+整除分块
懒得写式子了(QwQ)((Markdown)好难修。。。)

(Code:)

#include<bits/stdc++.h>
using namespace std;
namespace my_std
{
	typedef long long ll;
	#define fr(i,x,y) for(ll i=(x);i<=(y);i++)
	#define pfr(i,x,y) for(ll i=(y);i>=(x);i--)
	#define pf printf
	inline ll read()
	{
		ll sum=0,f=1;
		char ch=0;
		while(!isdigit(ch))
		{
			if(ch=='-') f=-1;
			ch=getchar();
		}
		while(isdigit(ch))
		{
			sum=(sum<<1)+(sum<<3)+(ch^48);
			ch=getchar();
		}
		return sum*f;
	}
	inline void write(ll x)
	{
	    if(x<0)
		{
	    	putchar('-');
			x=-x;
		}
	    if(x>9) write(x/10);
	    putchar(x%10+'0');
	}
}
using namespace my_std;
const ll N=5e4+50,hahaha=50000;
ll miu[N],sum[N],pri[N],mark[N],tot;
inline void cal_miu()
{
	miu[1]=1;
	for(ll i=2;i<=hahaha;i++)
	{
		if(!mark[i])pri[++tot]=i,miu[i]=-1;
		for(ll j=1;j<=tot&&i*pri[j]<=hahaha;j++)
		{
			mark[i*pri[j]]=1;
			if(i%pri[j]==0){miu[i*pri[j]]=0;break;}
			else miu[i*pri[j]]=-miu[i];
		}
	}
	for(ll i=1;i<=hahaha;i++)
	{
		sum[i]=sum[i-1]+miu[i];
	}
}
inline ll solve(ll n,ll m)
{
	if(n>m)swap(n,m);
	ll ans=0,pos;
	for(ll i=1;i<=n;i=pos+1)
	{
		pos=min(n/(n/i),m/(m/i));
		ans+=(sum[pos]-sum[i-1])*(n/i)*(m/i);
	}
	return ans;
}
int main(void)
{
	cal_miu();
	ll qwq=read();
	while(qwq--)
	{
		ll a=read(),b=read(),d=read();
		write(solve(a/d,b/d));
		putchar('
');
	}
	return 0;
}
原文地址:https://www.cnblogs.com/lgj-lgj/p/12335038.html