题目传送门
好题啊。。
解法:
gcd(x,y)其实就是这条直线上(包括(x,y))有多少个点。
然后因为能量损失是不包括((x,y))
所以每个点的能量损失其实是(gcd(x,y)-1)*2+1=gcd(x,y)*2+1
f[i]表示gcd(x,y)为i的对数。
f[i]=公因数为i的情况-最大公因数不是i的情况。
那么公因数为i的情况就等于(n/i)*(m/i)。
最大公因数不是i的情况就是f[2i],f[3i],f[4i]……
暴力减就好。
代码实现:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
ll n,m,f[110000];
int main() {
scanf("%lld%lld",&n,&m);
if(n>m)
swap(n,m);
ll ans=0;
for(int i=n;i>=1;i--) {
f[i]=(n/i)*(m/i);
for(int j=i+i;j<=n;j+=i)
f[i]-=f[j];
ans+=f[i]*(2*i-1);
}
printf("%lld\n",ans);
return 0;
}