题目链接

题目大意:在平面直角坐标系内有\(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;
}

相关文章:

  • 2021-07-05
  • 2021-09-13
  • 2022-12-23
  • 2021-07-22
猜你喜欢
  • 2021-08-10
  • 2021-06-30
  • 2022-01-01
  • 2021-07-13
  • 2021-10-17
  • 2022-03-08
  • 2022-01-05
相关资源
相似解决方案