题目大意:在平面直角坐标系内有\(n * m\)个点\((x,y)\),\(x \in [1,n]\),\(y \in [1,m]\),在\((0,0)\)位置有一台机器,如果机器和点\((x,y)\)之间的连线上有\(k\)个点的话那么就有\(2k-1\)的能量损失,给定\(n,m\)求能量损失之和
莫比乌斯反演
分析:
这题和[SDOI2008]仪仗队这题比较相似
假设我们可以看到一个点\((x,y)\),那么\((\lambda x,\lambda y)\),这个点我们是看不见的,换句话说,只有\(gcd(x,y)=1\)的点我们才看得见。进一步,如果\(gcd(x,y)=k\),那么从原点到点\((x,y)\)的线段上有\(k\)个点
也就是说我们求的是这玩意儿\(\sum_{i=1}^n\sum_{j=1}^m(2\times gcd(i,d)-1)\)
莫比乌斯反演就好了qaq
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 100;
int vis[maxn],n,m;
ll phi[maxn],ans;
vector<int> pri;
inline void sieve(){
phi[1] = 1;
for(int i = 2;i < maxn;i++){
if(!vis[i]){
pri.push_back(i);
phi[i] = i - 1;
}
for(int x : pri){
if(1ll * i * x >= maxn)break;
vis[i * x] = 1;
if(i % x)phi[i * x] = phi[i] * phi[x];
else{
phi[i * x] = phi[i] * x;
break;
}
}
}
for(int i = 1;i < maxn;i++)
phi[i] += phi[i - 1];
}
int main(){
sieve();
cin >> n >> m;
for(int r,l = 1;l <= min(n,m);l = r + 1){
r = min(min(n,m),min(n / (n / l),m / (m / l)));
ans += 2ll * (phi[r] - phi[l - 1]) * (n / l) * (m / l);
}
ans -= 1ll * n * m;
cout << ans << '\n';
return 0;
}