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;
}