[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) );
}
posted @ 2017-09-19 21:17  黑码的博客  阅读(126)  评论(0编辑  收藏  举报