SPOJ-VLATTICE

Description
Consider a N*N*N lattice. One corner is at (0,0,0) and the opposite one is at (N,N,N). How many lattice points are visible from corner at (0,0,0) ? A point X is visible from point Y iff no other lattice point lies on the segment joining X and Y.

Input :
The first line contains the number of test cases T. The next T lines contain an interger N

Output :
Output T lines, one corresponding to each test case.

Sample Input :
3
1
2
5

Sample Output :
7
19
175

Constraints :
T <= 50
1 <= N <= 1000000

题解:莫比乌斯反演

代码:

/*
* @Author: apple
* @Date:   2016-06-17 08:50:34
* @Last Modified by:   Heristor
* @Last Modified time: 2016-06-17 09:24:19
*/

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <ctime>
#include <vector>

using namespace std;

#define rep(i,l,r) for(i=l;i<=r;i++)
#define ser(i,r,l) for(i=r;i>=l;i--)
#define INF 1000005
#define inf 1000000007

typedef long long ll;
priority_queue<int >QwQ;

int T,n,tot=0;
int mu[INF],in[INF],Prime[INF];
ll tmp=0,Ans=0;
int read()
{
    int k=0,f=1;
    char ch;
    while(ch<'0' || ch>'9'){
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0' && ch<='9')k=(k<<1)+(k<<3)+ch-'0',ch=getchar();
    return k*f;
}
void init()
{
    int i,j,k;
    T=read();
    mu[1]=1;
    rep(i,2,1000000){
        if(!in[i]){
            mu[i]=-1;
            Prime[++tot]=i;
        }
        for(j=1;j<=tot && i*Prime[j]<=1000000;j++){
            in[i*Prime[j]]=1;
            if(!(i%Prime[j])){
                mu[i*Prime[j]]=0;
                break;
            }
            else mu[i*Prime[j]]=-mu[i];
        }
    }
    while(T--){
        Ans=3;
        n=read();
        rep(i,1,n){
            tmp=mu[i]*(n/i);
            tmp*=(ll)n/i;
            tmp*=(ll)n/i;
            Ans+=tmp;
            tmp=mu[i]*(n/i);
            tmp*=(ll)n/i;
            tmp*=3;
            Ans+=tmp;
        }
        printf("%lld\n", Ans);
    }
}
void work()
{
    int i,j,k;
}
int main()
{
    freopen("SpojVLATTICE.in","r",stdin);
    freopen("SpojVLATTICE.out","w",stdout);
    init();
    work();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值