莫比乌斯反演总结

知识及相关题题解链接:https://www.cnblogs.com/peng-ym/p/8647856.html
代码收藏:

BZOJ3994 [SDOI2015]约数个数和

#include<iostream>
#include<cstdio>
#include<cmath>
#define rg register
#define il inline
#define maxn 500005
#define ll long long
using namespace std;
il int read(){rg int x = 0 , w = 1 ; rg char ch = getchar();while (ch < '0' || ch > '9'){if (ch == '-') w = -1; ch = getchar();}while (ch >= '0' && ch <= '9'){x = (x << 3) + (x << 1) + ch - '0' ; ch = getchar();}return x * w;}
int primes[maxn] , mu[10000005] , cnt , k;
bool vis[10000005];
ll sum[maxn] , g[maxn];
void prime(int n){
	vis[1] = mu[1] = 1;
	for (rg int i = 2 ; i <= n ; ++i){
		if (!vis[i])
			primes[++cnt] = i , mu[i] = -1;
		for (rg int j = 1 ; j <= cnt && i * primes[j] <= n ; ++j){
			vis[i * primes[j]] = 1;
			if (!(i % primes[j])) break;
			mu[i * primes[j]] = -mu[i];	
		}
	}
	for (rg int i = 1 ; i <= n ; ++i)
		sum[i] = sum[i - 1] + mu[i];
	for (rg int i = 1 ; i <= n ; ++i){
		for (rg int l = 1 , r ; l <= i ; l = r + 1){
			r = i / (i / l);
			g[i] += (ll)(r - l + 1) * (ll)(i / l);
		}
	}
}
int main(){
	rg int t = read();
	prime(100005);
	while (t--){
		rg int a = read() , b = read();
		rg int maxrep = min(a , b);
		ll ans = 0;
		for (rg int l = 1 , r ; l <= maxrep ; l = r + 1){
			r = min(a / (a / l) , b / (b / l));
			ans += (sum[r] - sum[l - 1]) * g[a / l] * g[b / l];
		}
		printf("%lld\n" , ans);
	}
	return 0;	
}

BZOJ2301 [HAOI2011]Problem b

#include<iostream>
#include<cstdio>
#include<cmath>
#define rg register
#define il inline
#define maxn 500005
#define ll long long
using namespace std;
il int read(){rg int x = 0 , w = 1 ; rg char ch = getchar();while (ch < '0' || ch > '9'){if (ch == '-') w = -1; ch = getchar();}while (ch >= '0' && ch <= '9'){x = (x << 3) + (x << 1) + ch - '0' ; ch = getchar();}return x * w;}
int primes[maxn] , mu[10000005] , cnt , k;
bool vis[10000005];
ll sum[maxn];
void prime(int n){
	vis[1] = mu[1] = 1;
	for (rg int i = 2 ; i <= n ; ++i){
		if (!vis[i])
			primes[++cnt] = i , mu[i] = -1;
		for (rg int j = 1 ; j <= cnt && i * primes[j] <= n ; ++j){
			vis[i * primes[j]] = 1;
			if (!(i % primes[j])) break;
			mu[i * primes[j]] = -mu[i];	
		}
	}
	for (rg int i = 1 ; i <= n ; ++i)
		sum[i] = sum[i - 1] + mu[i];
}
ll f(int a , int b){
	rg int maxrep = min(a / k , b / k);
	ll ans = 0;
	for (rg int l = 1 , r ; l <= maxrep ; l = r + 1){
		r = min(a / (a / l) , b / (b / l));
		ans += (ll)(sum[r] - sum[l - 1]) * (ll)(a / (l * k)) * (ll)(b / (l * k)); 
	}
	return ans;
}
int main(){
	rg int t = read();
	prime(100005);
	while (t--){
		rg int a = read() , b = read() , c = read() , d = read();
		k = read();
		ll ans = f(b,  d) - f(a - 1, d) - f(b , c - 1) + f(a - 1, c - 1);
		printf("%lld\n" , ans);	
	}
	return 0;	
}

BZOJ1101 [POI2007]Zap

#include<iostream>
#include<cstdio>
#include<cmath>
#define rg register
#define il inline
#define maxn 500005
#define ll long long
using namespace std;
il int read(){rg int x = 0 , w = 1 ; rg char ch = getchar();while (ch < '0' || ch > '9'){if (ch == '-') w = -1; ch = getchar();}while (ch >= '0' && ch <= '9'){x = (x << 3) + (x << 1) + ch - '0' ; ch = getchar();}return x * w;}
int primes[maxn] , mu[10000005] , cnt;
bool vis[10000005];
ll sum[maxn];
void prime(int n){
	vis[1] = mu[1] = 1;
	for (rg int i = 2 ; i <= n ; ++i){
		if (!vis[i])
			primes[++cnt] = i , mu[i] = -1;
		for (rg int j = 1 ; j <= cnt && i * primes[j] <= n ; ++j){
			vis[i * primes[j]] = 1;
			if (!(i % primes[j]))
				break;
			else
				mu[i * primes[j]] = mu[i] * -1;	
		}
	}
	for (rg int i = 1 ; i <= n ; ++i)
		sum[i] = sum[i - 1] + mu[i];
}
int main(){
	rg int t = read();
	prime(100002);
	while(t--){
		rg int a = read() , b = read() , d = read();
		rg int maxrep = min(a / d , b / d);
		ll ans = 0;
		for (rg int l = 1 , r ; l <= maxrep ; l = r + 1){
			r = min(a / (a / l) , b / (b / l) );
			ans += (ll)(a / (l * d)) * (ll)(b / (l * d)) * (ll)(sum[r] - sum[l - 1]);
		}
		printf("%lld\n" , ans);
	}
	return 0;	
}	
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值