首页 > 代码库 > SPOJ_VLATTICE
SPOJ_VLATTICE
题目是给你一个空间,和一个点(n,n,n),求从原点出发能够直接接触多少个点(不经过任何一个点)?
典型的mobius反演即可。
首先,ans=3,因为(1,0,0),(0,1,0),(0,0,1)这三个点必看。
其次别在三个平面内反演一次,算出三个坐标轴面的可见点数。
最后在空间反演一次,即可。反演的方法都是分块即可。
召唤代码君:
#include <iostream>#include <cstdio>#include <cstring>#define maxn 1001000typedef long long ll;using namespace std;int mu[maxn],smu[maxn],pri[maxn];ll n;ll f[maxn],g[maxn];void getprim_mu(){ for (int i=1; i<maxn; i++) mu[i]=1; for (int i=2; i<maxn; i++) { if (pri[i]) continue; mu[i]=-mu[i]; for (int j=i+i; j<maxn; j+=i) pri[j]=1,mu[j]=-mu[j]; if (maxn/i>=i) for (int j=i*i; j<maxn; j+=i*i) mu[j]=0; } for (int i=1; i<maxn; i++) smu[i]=smu[i-1]+mu[i];}ll getnum(ll N){ int next; ll ans=0; for (int i=1; i<=N; i=next+1) { next=N/(N/i); ans+=(smu[next]-smu[i-1])*(N/i)*(N/i); } return ans;}void _init(){ scanf("%lld",&n); f[1]=getnum(n);}int gcd(int A,int B) { return B==0?A:gcd(B,A%B); }int main(){ getprim_mu(); int T; ll ans; scanf("%d",&T); while (T--) { _init(); ans=3+3*f[1]; for (int i=1,next; i<=n; i=next+1) { next=n/(n/i); ans+=(n/i)*(n/i)*(n/i)*(smu[next]-smu[i-1]); } printf("%lld\n",ans); } return 0;}
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。