关于莫比乌斯函数的塞 : 莫比乌斯前n项和 , 莫比乌斯函数绝对值的前n项和

https://ac.nowcoder.com/acm/contest/874#submit/{%22problemIdFilter%22%3A25455%2C%22statusTypeFilter%22%3A%225%22}

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
#define CLR(a,b) memset((a),(b),sizeof((a)))
typedef long long ll;
const int N = 5000000;
bool check[N+10];
int prime[N+10],tot;
int mu[N+10];
ll mu_sum[N+10];
void Moblus(){
    CLR(check, false);
    mu[1] = 1;
     tot = 0;
    for(int i = 2; i <= N; i++){
        if( !check[i] ){
            prime[tot++] = i;
            mu[i] = -1;
        }
        for(int j = 0; j < tot && i*prime[j] <= N; j++){
            check[i * prime[j]] = true;
            if( i % prime[j] == 0){
                mu[i * prime[j]] = 0;
                break;
            }
            else
                mu[i * prime[j]] = -mu[i];
        }
    }
    mu_sum[0]=0;
    for(int i = 1; i <= N; ++i){
        mu_sum[i] = mu_sum[i-1] + mu[i];

    }

}
map<ll,ll> mp;
ll Mertens(ll n){
    if(n <= N) return mu_sum[n];
    if(mp.count(n)) return mp[n];
    ll ans = 1, ed;
    for(ll i = 2; i <= n; i = ed+1){
        ed = n/(n/i);
        ans -= (ed - i + 1)*Mertens(n/i);
    }
    return mp[n] = ans;
}

int main(){

    Moblus();
    for(int i=1 ; i<=20 ; i++)
        printf("%d ",mu[i]);
    int ncase;
    scanf("%d",&ncase);
    while(ncase--){

            mp.clear();
    ll a,k;
    scanf("%lld%lld", &a, &k);

    if(k==0){
        printf("%lld\n",a);
        continue;
    }
    if(k%2){
    printf("%lld\n", Mertens(a) );
    continue;

    }
    else{
          ll ans=0;
          ll t=sqrt(a);
          for(int i=1 ; i<= t; i++)
          {
                ll T=a/i;
                T/=i;
                ans+=mu[i]*T;

          }
        printf("%lld\n",ans);
    }

    }
    return 0;
}
View Code

 

posted @ 2019-04-28 17:20  shuai_hui  阅读(295)  评论(0编辑  收藏  举报