SPOJ VLATTICE Visible Lattice Points - 莫比乌斯反演

题目描述

一开始把坐标想成(1,1,1)开始,却在算斜率的时候忘记-(1,1,1),至此陷入歧途。最后忍无可忍看了题解。。。

看的这个,就粘这个了

想懂了还是很清楚的。

#include<cstdio>
#define MAXN 1000000
#define MAXP 80000
int mu[MAXN+10],cntpr,prime[MAXP+10],sum[MAXN+10],a;
bool isprime[MAXN+10];

void CalMobius(int n)
{
    mu[1]=1;
    for(int i=2;i<=n;i++){
        if(!isprime[i]){
            prime[++cntpr]=i;
            mu[i]=-1;
        }
        for(int j=1;prime[j]*i<=n&&j<=cntpr;j++){
            isprime[prime[j]*i]=true;
            if(i%prime[j]==0){
                mu[prime[j]*i]=0;
                break;
            }
            mu[prime[j]*i]=-mu[i];
        }
    }
    for(int i=1;i<=n;i++)
        sum[i]=mu[i]+sum[i-1];
}
long long Cal1(int n)
{
    int last;
    long long ret=0;
    for(int i=1;i<=n;i=last+1){
        last=n/(n/i);
        ret+=1LL*(sum[last]-sum[i-1])*(n/i)*(n/i)*(n/i);
    }
    return ret;
}
long long Cal2(int n)
{
    int last;
    long long ret=0;
    for(int i=1;i<=n;i=last+1){
        last=n/(n/i);
        ret+=1LL*(sum[last]-sum[i-1])*(n/i)*(n/i);
    }
    return ret;
}
int main()
{
    int T;
    scanf("%d",&T);
    CalMobius(MAXN);
    while(T--){
        scanf("%d",&a);
        printf("%lld\n",Cal1(a)+Cal2(a)*3+3);
    }
}
posted @ 2016-01-27 16:03  KatarinaYuan  阅读(101)  评论(0编辑  收藏  举报