P1447 [NOI2010] 能量采集

原题链接
考察:莫比乌斯反演
思路:
  发现gcd(i,j) = 1的损失能量都是1,gcd(i,j) = 2的,损失能量都是3...由此枚举gcd(i,j) = k,求\((n,m)\)范围内\(gcd(i,j) = k\)的对数.时间复杂度大概是\(O(n^{3/2})\)

Code

#include <iostream> 
#include <cstring>
using namespace std;
typedef long long LL;
const int N = 500010;
int n,m,prime[N],cnt,mob[N],sum[N];
bool st[N];
void GetPrime(int n)
{
	mob[1] = 1;
	for(int i=2;i<=n;i++)
	{
		if(!st[i]) prime[++cnt] = i,mob[i] = -1;
		for(int j=1;prime[j]<=n/i;j++)
		{
			st[i*prime[j]] = 1;
			if(i%prime[j]==0) break;
			mob[i*prime[j]] = mob[i]*(-1);
		}
	}
	for(int i=1;i<=n;i++)
	  sum[i] = sum[i-1]+mob[i];
}
int main()
{
	scanf("%d%d",&n,&m);
	GetPrime(N-1);
	if(n>m) swap(n,m);
	LL ans = 0;
	for(int k=1;k<=n;k++)
	{
		int a = n/k,b = m/k,s = 2*k-1;
		for(int l=1,r;l<=a;l=r+1)
		{
			r = min(a/(a/l),b/(b/l));
			ans += (LL)s*(sum[r]-sum[l-1])*(a/l)*(b/l);
		}
	}
	printf("%lld\n",ans);
	return 0;
}
posted @ 2021-06-17 16:07  acmloser  阅读(31)  评论(0编辑  收藏  举报