洛谷 P2257:YY的GCD(莫比乌斯反演 | 莫比乌斯函数性质)

洛谷 P2257:YY的GCD(莫比乌斯反演 | 莫比乌斯函数性质)_第1张图片


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

转化一下式子,枚举 p: ∑ p = 2 n ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = p ] , p ∈ p r i m e \sum_{p = 2}^n\sum_{i = 1}^n\sum_{j = 1}^m[gcd(i,j) = p],p\in prime p=2ni=1nj=1m[gcd(i,j)=p],pprime
这个式子等价于: ∑ p = 2 n ∑ i = 1 ⌊ n p ⌋ ∑ j = 1 ⌊ m p ⌋ [ g c d ( i , j ) = 1 ] , p ∈ p r i m e \sum_{p = 2}^n\sum_{i = 1}^{\lfloor\frac{n}{p}\rfloor}\sum_{j = 1}^{\lfloor\frac{m}{p}\rfloor}[gcd(i,j) = 1],p\in prime p=2ni=1pnj=1pm[gcd(i,j)=1],pprime
根据莫比乌斯函数性质, [ g c d ( i , j ) = 1 ] [gcd(i,j) = 1] [gcd(i,j)=1]可以替换成: ∑ d ∣ g c d ( i , j ) μ ( d ) \sum_{d | gcd(i,j)}\mu(d) dgcd(i,j)μ(d),整个式子变成: ∑ p = 2 n ∑ i = 1 ⌊ n p ⌋ ∑ j = 1 ⌊ m p ⌋ ∑ d ∣ g c d ( i , j ) μ ( d ) , p ∈ p r i m e \sum_{p = 2}^n\sum_{i = 1}^{\lfloor\frac{n}{p}\rfloor}\sum_{j = 1}^{\lfloor\frac{m}{p}\rfloor}\sum_{d | gcd(i,j)}\mu(d),p\in prime p=2ni=1pnj=1pmdgcd(i,j)μ(d),pprime
∑ i = 1 ⌊ n p ⌋ ∑ j = 1 ⌊ m p ⌋ ∑ d ∣ g c d ( i , j ) μ ( d ) \sum_{i = 1}^{\lfloor\frac{n}{p}\rfloor}\sum_{j = 1}^{\lfloor\frac{m}{p}\rfloor}\sum_{d | gcd(i,j)}\mu(d) i=1pnj=1pmdgcd(i,j)μ(d) 这里改变一下枚举项,枚举 d: ∑ p = 2 n ∑ d = 1 ⌊ n p ⌋ μ ( d ) ∑ i = 1 ⌊ n p ∗ d ⌋ ∑ j = 1 ⌊ m p ∗ d ⌋ , p ∈ p r i m e \sum_{p = 2}^n\sum_{d = 1}^{\lfloor\frac{n}{p}\rfloor}\mu(d)\sum_{i = 1}^{\lfloor\frac{n}{p*d}\rfloor}\sum_{j = 1}^{\lfloor\frac{m}{p*d}\rfloor},p\in prime p=2nd=1pnμ(d)i=1pdnj=1pdm,pprime
这时右半边直接等于: ⌊ n p ∗ d ⌋ ∗ ⌊ m p ∗ d ⌋ \lfloor\frac{n}{p * d}\rfloor*\lfloor\frac{m}{p * d}\rfloor pdnpdm,化简到这一步可以两层数论分块,单组O(n)解决,但题目有T组,复杂度还需要优化。
T = p ∗ d T = p * d T=pd ∑ p = 2 n ∑ d = 1 ⌊ n p ⌋ μ ( d ) ∗ ⌊ n T ⌋ ∗ ⌊ m T ⌋ , p ∈ p r i m e \sum_{p = 2}^n\sum_{d = 1}^{\lfloor\frac{n}{p}\rfloor}\mu(d)*\lfloor\frac{n}{T}\rfloor*\lfloor\frac{m}{T}\rfloor ,p\in prime p=2nd=1pnμ(d)TnTm,pprime

再改变枚举项,枚举T: ∑ T = 1 n ⌊ n T ⌋ ∗ ⌊ m T ⌋ ∗ ∑ p ∣ T μ ( T p ) , p ∈ p r i m e \sum_{T = 1}^n\lfloor\frac{n}{T}\rfloor*\lfloor\frac{m}{T}\rfloor*\sum_{p | T}\mu(\frac{T}{p}),p\in prime T=1nTnTmpTμ(pT),pprime
注意此时莫比乌斯函数部分可以预处理,令 F ( T ) = ∑ p ∣ T μ ( T p ) F(T) = \sum_{p | T}\mu(\frac{T}{p}) F(T)=pTμ(pT),可以用埃筛在 n l o g l o g n nloglogn nloglogn时间内筛出 F F F函数,再求一下前缀和,然后数论分块即可在单组 s q r t ( n ) sqrt(n) sqrt(n)时间内完成
复杂度为 O ( T ∗ s q r t ( n ) ) O(T * sqrt(n)) O(Tsqrt(n)),T为询问组数


代码:
(太多的long long 运算会超时)

#include
using namespace std;
const int maxn = 1e7 + 10;
const int mx = 1e7;
typedef long long ll;
int t,n,m;
bool ispri[maxn];
int pri[maxn];
int mu[maxn];
int sum[maxn];
void sieve(int n) {
	mu[1] = 1;
	ispri[0] = ispri[1] = true;
	pri[0] = 0;
	for(int i = 2; i <= n; i++) {
		if(!ispri[i]) {
			pri[++pri[0]] = i;
			mu[i] = -1;
		}
		for(int j = 1; j <= pri[0] && i * pri[j] <= n; j++) {
			ispri[i * pri[j]] = true;
			if(i % pri[j] == 0) break;
			mu[i * pri[j]] = -mu[i];
		}
	}
	for(int i = 1; i <= pri[0]; i++)
		for(int j = 1; j * pri[i] <= n; j++)
			sum[j * pri[i]] += mu[j];
	for(int i = 1; i <= n; i++)
		sum[i] += sum[i - 1];
}
int main() {
	scanf("%d",&t);
	sieve(10000000);
	while(t--) {
		scanf("%d%d",&n,&m);
		if(n > m) swap(n,m);
		int i,j;
		ll res = 0;
		for(i = 1; i <= n; i = j + 1) {
			j = min(n / (n / i),m / (m / i));
			int p1 = n / i,p2 = m / i;
			res += 1ll * p1 * p2 * (sum[j] - sum[i - 1]);
		}
		printf("%lld\n",res);
	}
	return 0;
}

你可能感兴趣的:(莫比乌斯反演,莫比乌斯函数,数论分块,莫比乌斯函数性质,莫比乌斯反演入门,数论分块)