Loading

Visible Lattice Points 题解

Visible Lattice Points

题目大意#

给定一个 N×N×N 的由若干点组成的立方体,点的坐标从 (0,0,0)(N,N,N),求从点 (0,0,0) 处可以看见多少个点。

思路分析#

我们将立方体上的点分成三类:

  • xy,yz,xz 平面上的点。
  • x,y,z 轴上的点。
  • 即不在平面,也不在坐标轴上的点。

就可以简单得出我们需要求的式子:

i=1nj=1nk=1n[gcd(i,j,k)=1]+3i=1nj=1n[gcd(i,j)=1]+3

然后就可以开始愉快的颓柿子了:

i=1nj=1nk=1n[gcd(i,j,k)=1]=d=1nμ(d)i=1nj=1nk=1n[d|i][d|j][d|k]=d=1nμ(d)nd3

类似的,

i=1nj=1n[gcd(i,j)=1]=d=1nμ(d)i=1nj=1m[d|i][d|j]=d=1nμ(d)nd2

因此,我们的答案就是:

3+d=1nμ(d)nd2(nd+3)

只需要线性筛出 μ 的前缀和,再通过整除分块就可以在 O(n) 的时间复杂度内得出结果。

代码:#

#include <bits/stdc++.h>
using namespace std;
const int N=1111111,L=1000000;
#define int long long\\好习惯

int T,n,ans,cnt;
int v[N],prime[N],mu[N];

void sieve(){
    mu[1]=1;
    for(int i=2;i<=L;i++){
        if(!v[i]){prime[++cnt]=i;mu[i]=-1;}
        for(int j=1;j<=cnt&&i*prime[j]<=L;j++){
            v[i*prime[j]]=1;
            if(i%prime[j]==0) break;
            mu[i*prime[j]]=-mu[i];
        }
    }
    for(int i=1;i<=L;i++) mu[i]+=mu[i-1];\\计算前缀和
}

signed main(){
    sieve();
    scanf("%lld",&T);
    while(T--){
        scanf("%lld",&n);
        ans=0;
        for(int l=1,r;l<=n;l=r+1){//简单的整除分块
            r=n/(n/l);
            ans+=(mu[r]-mu[l-1])*((n/l)*(n/l)*(3+(n/l)));\\根据式子计算结果
        }ans+=3;
        cout<<ans<<'\n';
    }
    return 0;
}

作者:TKXZ133

出处:https://www.cnblogs.com/TKXZ133/p/17458282.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   TKXZ133  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示