题目链接

题目大意:求\(\sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j)\text{是素数}]\)

莫比乌斯反演


解析:

首先我们定义函数\(f(x) = \begin{cases}1 & \text{x是素数} \\ 0 & \text{其他情况}\end{cases}\)

我们要求的就是:

\(\sum_{i=1}^{n}\sum_{j=1}^{m}f(gcd(i,j))\)

然后\(d \mid gcd(i,j) \Longleftrightarrow d | i,d|j\)

假设我们找到了一个函数\(g\),满足:

\[f(x)=\sum_{d\mid x}g(x) \]

那么

\[\begin{aligned} ans&=\sum_{i=1}^{n}\sum_{j=1}^{m}\sum_{d\mid i,d\mid j}g(d) \\ &= \sum_{d=1}^{min(n,m)}g(d)\sum_{i=1}^{n}\sum_{j=1}^{m}[d \mid i][d \mid j] \\ &= \sum_{d=1}^{min(n,m)}g(d){\lfloor \frac{n}{d} \rfloor \lfloor \frac{m}{d} \rfloor}\end{aligned} \]

假如我们预处理出\(g\)的前缀和,利用整除分块我们便可以快速求出整个式子的值

我们尝试着把\(g\)表示出来

\[f = g * 1 \Longleftrightarrow g = f * \mu \]

\[\begin{aligned}g(x)&=\sum_{d \mid x}[x\text{是素数}]\mu(\frac{x}{d}) \\ &= \sum_{p \mid x}\mu(\frac{x}{p}) \quad \text{p是素数}\end{aligned} \]

\(g\)我们可以筛出\(\mu\),然后枚举每一个素数,计算它的贡献

#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn = 1e7 + 100;
int g[maxn],mu[maxn],vis[maxn];
inline int query(int a,int b){return g[b] - g[a - 1];}
vector<int> pri;
inline void init(){
	mu[1] = 1;
	for(int i = 2;i <= maxn;i++){
		if(!vis[i]){
			pri.push_back(i);
			mu[i] = -1;
		}
		for(int x : pri){
			if(i * x >= maxn)break;
			vis[i * x] = 1;
			if(i % x){
				mu[i * x] = mu[i] * mu[x];
			}else{
				mu[i * x] = 0;
				break;
			}
		}
	}
	for(int x : pri)
		for(int i = 1;i * x < maxn;i++)
			g[i * x] += mu[i];
	for(int i = 1;i < maxn;i++)g[i] += g[i - 1];
}
int t,n,m;
inline void solve(){
	cin >> n >> m;
	ll ans = 0;
	for(int l = 1,r;l <= min(n,m);l = r + 1){
		r = min(n / (n / l),m / (m / l));
		ans += (ll)query(l,r) * (n / l) * (m / l);
	}
	cout << ans << '\n';
}
int main(){
	init();
	cin >> t;
	while(t--)solve();
	return 0;
}

相关文章:

  • 2021-12-15
  • 2022-02-12
  • 2021-11-13
  • 2021-08-29
  • 2022-12-23
  • 2021-12-08
猜你喜欢
  • 2021-10-28
  • 2021-06-11
  • 2021-06-20
  • 2021-12-13
  • 2021-12-03
  • 2021-12-19
相关资源
相似解决方案