luoguP1447 [NOI2010]能量采集

题意

显然答案是\(\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}2*\gcd(i,j)-1\)
转化下即为:\((2*\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}\gcd(i,j))-n*m\)

考虑如何求:\(\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}\gcd(i,j)\)
枚举\(gcd\),即求:
\(\sum\limits_{d=1}^{\min(n,m)}d*\sum\limits_{i=1}^n\sum\limits_{j=1}^m[gcd(i,j)=d]\)

这就是莫比乌斯反演裸题了,做法见这题

code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=100010;
typedef long long ll;
int n,m;
ll ans;
int mu[maxn],sum[maxn];
bool vis[maxn];
vector<int>prime;
inline void shai(int n)
{
	vis[1]=1;mu[1]=1;
	for(int i=2;i<=n;i++)
	{
		if(!vis[i])prime.push_back(i),mu[i]=-1;
		for(unsigned int j=0;j<prime.size()&&i*prime[j]<=n;j++)
		{
			vis[i*prime[j]]=1;
			if(i%prime[j]==0)break;
			mu[i*prime[j]]=-mu[i];
		}
	}
	for(int i=1;i<=n;i++)sum[i]=sum[i-1]+mu[i];
}
inline ll solve(int n,int m,int d)
{
	ll res=0;
	for(int l=1,r;l<=min(n,m)/d;l=r+1)
	{
		r=min(n/(n/l),m/(m/l));
		res+=1ll*(sum[r]-sum[l-1])*(n/(1ll*l*d))*(m/(1ll*l*d));
	}
	return res;
}
int main()
{
	shai(100000);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=min(n,m);i++)ans+=2ll*i*solve(n,m,i);
	printf("%lld",ans-1ll*n*m);
	return 0;
}
posted @ 2019-11-27 17:24  nofind  阅读(90)  评论(0编辑  收藏  举报