1. 程式人生 > >[51nod1244]莫比烏斯函數之和

[51nod1244]莫比烏斯函數之和

break () include ++ urn ack stack amp light

推公式,設$A(n)=\sum\limits_{i=1}^n\mu(i)$,令$B(n)=1$,則推出$C(n)=(A*B)(n)=[n=1]$

$$\begin{align*}\sum\limits_{i=1}^n[i=1]&=\sum\limits_{i=1}^n\sum\limits_{d|i}\mu(d)\\1&=\sum\limits_{d=1}^n\sum\limits_{\substack{d|i\\i\leq n}}\mu(d)\\1&=\sum\limits_{d=1}^n\mu(d)\left\lfloor\dfrac nd\right\rfloor\\1&=\sum\limits_{d=1}^nA\left(\left\lfloor\dfrac nd\right\rfloor\right)\\A(n)&=1-\sum\limits_{d=2}^nA\left(\left\lfloor\dfrac nd\right\rfloor\right)\end{align*}$$

然後就做完了

#include<stdio.h>
#include<map>
using namespace std;
#define ll long long
#define T 1000000
int pr[1000010],mu[1000010];
bool np[1000010];
void sieve(){
	ll i,j,m=0;
	np[1]=1;
	mu[1]=1;
	for(i=2;i<=T;i++){
		if(!np[i]){
			m++;
			pr[m]=i;
			mu[i]=-1;
		}
		for(j=1;j<=m;j++){
			if(pr[j]*i>T)break;
			np[i*pr[j]]=1;
			if(i%pr[j]==0)break;
			mu[i*pr[j]]=-mu[i];
		}
	}
	for(i=2;i<=T;i++)mu[i]+=mu[i-1];
}
map<ll,ll>res;
map<ll,ll>::iterator it;
ll dj(ll n){
	if(n<=T)return mu[n];
	it=res.find(n);
	if(it!=res.end())return it->second;
	ll i,las,s=1;
	for(i=2;i<=n;i=las+1){
		las=n/(n/i);
		s-=(las-i+1)*dj(n/i);
	}
	return res[n]=s;
}
int main(){
	sieve();
	ll l,r;
	scanf("%lld%lld",&l,&r);
	printf("%lld",dj(r)-dj(l-1));
}

[51nod1244]莫比烏斯函數之和