[51nod1244]莫比乌斯函数之和
莫比乌斯函数,由德国数学家和天文学家莫比乌斯提出。梅滕斯(Mertens)首先使用μ(n)(miu(n))作为莫比乌斯函数的记号。具体定义如下:
如果一个数包含平方因子,那么miu(n) = 0。例如:miu(4), miu(12), miu(18) = 0。
如果一个数不包含平方因子,并且有k个不同的质因子,那么miu(n) = (-1)^k。例如:miu(2), miu(3), miu(30) = -1,miu(1), miu(6), miu(10) = 1。
给出一个区间a,ba,b,S(a,b) = miu(a) + miu(a + 1) + …… miu(b)。
例如:S(3, 10) = miu(3) + miu(4) + miu(5) + miu(6) + miu(7) + miu(8) + miu(9) + miu(10)
= -1 + 0 + -1 + 1 + -1 + 0 + 0 + 1 = -1。
Input
输入包括两个数a, b,中间用空格分隔(2 <= a <= b <= 10^10)
Output
输出S(a, b)。
Sample Input
3 10
Sample Output
-1
大佬的推导:http://blog.csdn.net/alan_cty/article/details/51836476
这个大佬写得很好呀 其实难点就是积性函数的几个性质,根据 f(6)模拟一下就知道
f(6)=0,自己是写了个学完后的推导过程但是太丑了。难点在于里面的要外移,弄好以后用map加速就好(分块太难,不会。。)
#include <bits/stdc++.h>
using namespace std;
const int N = 5000000;
typedef long long ll;
int vis[N+10];
int prime[N+10],mu[N+10];
int cnt;
ll sum[N+10];
map<ll,ll> mp;
void Init(){
mu[1] = 1;
cnt = 0;
for(int i=2; i<=N; i++){
if(!vis[i]){
prime[cnt++] = i;
mu[i] = -1;
}
for(int j=0; j<cnt&&i*prime[j]<=N; j++){
vis[i*prime[j]] = 1;
if(i%prime[j]) mu[i*prime[j]] = -mu[i];
else{
mu[i*prime[j]] = 0;
break;
}
}
}
sum[0]=0;
for(int i=1;i<=N;i++)
{
sum[i]=sum[i-1]+mu[i];
}
}
ll solve(ll x)
{
if(x<=N) return sum[x];
if(mp.count(x)) return mp[x];
ll res=1;
for(ll i=2,nxt=0;i<=x;i=nxt+1){
nxt=x/(x/i);
res-=(nxt-i+1)*solve(x/i);
}
mp[x]=res;
return res;
}
int main()
{
ll a,b;
Init();
scanf("%lld%lld",&a,&b);
printf("%lld\n",solve(b)-solve(a-1) );
}