解题报告:SPOJ - VLATTICE Visible Lattice Points 莫比乌斯反演

题目链接

题意:

有一个边长为n的立方体,你位于(0,0,0)处,问能看见的格子数目。

某个格子能被看见当且仅当它与原点的连线上不存在其他的格子。


思路:

之前做过一个二维的版本:HDU2841 Visible Trees 莫比乌斯反演

思路是差不多的,分成三个部分求:

对于(x!=0&&y!=0&&z!=0)的所有点,要求 gcd(x,y,z)==1的点数

然后三个面上的点分别求gcd(x,y)==1 , gcd(x,z)==1 ,gcd(y,z)==1 的点数,很明显每个面的点数是一样多的。

最后加上三个位于轴上的点即可


代码:

#include<bits/stdc++.h>

using namespace std;

const int N = 1e6+10;

vector<int>pr;
bool Np[N];
int sum[N];


void init(){
   sum[1] = 1;
   for(int i=2;i<N;i++){
      if(!Np[i]){
         sum[i] = -1;
         pr.emplace_back(i);
      }for(int j=0;j<pr.size();j++){
         int t = pr[j] * i;
         if(t>=N)break;
         Np[t] = true;
         if(i%pr[j]==0){
            sum[t] = 0;
            break;
         }sum[t] = - sum[i];
      }sum[i] += sum[i-1];
   }
}

int main()
{
   init();
   int T;
   scanf("%d",&T);
   while(T--){
      int n;
      scanf("%d",&n);
      long long ans = 3;
      for(int i=1,last;i<=n;i=last+1){
         last = n/(n/i);
         ans += 1LL * (sum[last]-sum[i-1]) * (n/i) * (n/i) * ( (n/i) + 3 ) ;
      }printf("%lld\n",ans);
   }return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值