P2257 YY的GCD(莫比乌斯反演入门)

这是一篇关于利用莫比乌斯反演解决数学计数问题的博客,具体是针对P2257题目中gcd等于质数的个数进行讨论。博主通过建立F(n)与f(d)之间的关系,应用莫比乌斯反演公式,将原始问题转换为求解f(p),并详细解释了如何通过整除分块和预处理莫比乌斯函数前缀和来优化算法,达到O(n)+T*O(n)的时间复杂度。
摘要由CSDN通过智能技术生成

题目链接

题意:求 ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = = p r i m e ] \sum_{i=1}^{n} \sum_{j=1}^{m} [gcd(i,j) == prime] i=1nj=1m[gcd(i,j)==prime]

思路:

f ( d ) f(d) f(d) g c d ( x , y ) = = d gcd(x,y) == d gcd(x,y)==d 的个数, F ( n ) F(n) F(n) g c d ( x , y ) = = n gcd(x,y) == n gcd(x,y)==n n n n 的倍数的个数 ( x ∈ [ 1 , n ] x \in [1, n] x[1,n] y ∈ [ 1 , m ] y \in [1,m] y[1,m] )

这样的话这两个式子的关系是这样的 F ( n ) = ∑ n ∣ d f ( d ) F(n) = \sum_{n|d} f(d) F(n)=ndf(d)

题目的表达式可以变成这样: ∑ p ∈ p r i m e ∑ i = 1 n ∑ j = 1 m [ g c d ( x , y ) = = 1 ] \sum_{p\in prime}\sum^{n}_{i=1}\sum^{m}_{j=1}[gcd(x,y)==1] pprimei=1nj=1m[gcd(x,y)==1]

根据假设可以变换成: ∑ p ∈ p r i m e f ( p ) \sum_{p\in prime} f(p) pprimef(p)

根据莫比乌斯反演( f ( n ) = ∑ n ∣ d m u ( d n ) F ( d ) f(n) = \sum_{n|d} mu(\frac{d}{n})F(d) f(n)=ndmu(nd)F(d) ) 可以转换 f ( p ) f(p) f(p) ∑ p ∈ p r i m e ∑ p ∣ d m u ( d p ) F ( d ) \sum_{p\in prime} \sum_{p|d} mu(\frac{d}{p})F(d) pprimepdmu(pd)F(d)

把枚举的 d d d 换成 d p \frac{d}{p} pd 这样式子就变成: ∑ p ∈ p r i m e ∑ d = 1 m i n ( n p , m p ) m u ( d ) F ( d p ) \sum_{p\in prime} \sum_{d=1} ^{min(\frac{n}{p},\frac{m}{p})} mu(d)F(dp) pprimed=1min(pn,pm)mu(d)F(dp)

将dp替换为T: ∑ p ∈ p r i m e ∑ T = 1 m i n ( n , m ) m u ( T p ) F ( T ) \sum_{p\in prime} \sum_{T=1} ^{min(n,m)} mu(\frac{T}{p})F(T) pprimeT=1min(n,m)mu(pT)F(T)

求和符号换个顺序: ∑ T = 1 m i n ( n , m ) ∑ p ∣ T a n d p ∈ p r i m e m u ( T p ) F ( T ) \sum_{T=1}^{min(n,m)} \sum_{p|T and p\in prime} mu(\frac{T}{p})F(T) T=1min(n,m)pTandpprimemu(pT)F(T)

这样就可以把 F ( T ) F(T) F(T) 提出来得到: ∑ T = 1 m i n ( n , m ) F ( T ) ∑ p ∣ T p ∈ p r i m e m u ( T p ) \sum_{T=1}^{min(n,m)}F(T) \sum_{p|T \\ p\in prime} mu(\frac{T}{p}) T=1min(n,m)F(T)pTpprimemu(pT)

即: ∑ T = 1 m i n ( n , m ) ⌊ n T ⌋ × ⌊ m T ⌋ ∑ p ∣ T p ∈ p r i m e m u ( T p ) \sum_{T=1}^{min(n,m)} \lfloor \frac{n}{T} \rfloor \times \lfloor \frac{m}{T} \rfloor \sum_{p|T \\ p\in prime} mu(\frac{T}{p}) T=1min(n,m)Tn×TmpTpprimemu(pT)

用整除分块搞出每一块的值,预处理莫比乌斯函数的前缀和当作这一块的权值。

处理莫比乌斯函数的时候枚举质数,下标为质数的i倍的mu值就是mu[i] 的值,这个从式子里很好看得出,然后求一个前缀和当作整除分块的一整块的权值就可以了。 O ( n ) + T ∗ O ( n ) O(n)+T*O(\sqrt{n}) O(n)+TO(n )

#include <bits/stdc++.h>
using namespace std;

const int MAX = 1e7;
bool check[MAX+10];
int prime[MAX+10], g[MAX+10], mu[MAX+10], sum[MAX+10];
void Mobius() {
	memset(check,false,sizeof(check));
	mu[1] = 1;
	int tot = 0;
	for(int i = 2; i <= MAX; i++) {
		if( !check[i] ) {
			prime[tot++] = i;
			mu[i] = -1;
		}
		for(int j = 0; j < tot; j++) {
			if(i * prime[j] > MAX) break;
			check[i * prime[j]] = true;
			if( i % prime[j] == 0) {
				mu[i * prime[j]] = 0;
				break;
			} else {
				mu[i * prime[j]] = -mu[i];
			}
		}
	}
	
	for(int i = 0;i < tot; i++) {
		for(int j = 1; j * prime[i] <= MAX; j++) {
			g[j * prime[i]] += mu[j];
		}
	}
	for(int i = 1;i <= MAX; i++) sum[i] = sum[i-1] + g[i];
}

int _, n, m;

int main() {
	Mobius();
	scanf("%d", &_);
	while(_--) {
		scanf("%d %d", &n, &m);
		int k = min(n, m), i, j;
		long long ans = 0;
		for(i = 1;i <= k; i = j+1) {
			j = min(m/(m/i), n/(n/i));
			ans += ((long long)(n/i) * (long long)(m/i)) * (sum[j] - sum[i-1]);
		}
		printf("%lld\n", ans);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值