首页 > 代码库 > spoj 7001 Visible Lattice Points莫比乌斯反演
spoj 7001 Visible Lattice Points莫比乌斯反演
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
题目大意:从点(0,0,0)出发的直线可看到多少个点(只能看到第一个,后面的视为挡住了看不见)。
解题思路:求gcd(x,y,z)=1的点有多少个,F(n) 表示满足条件的 gcd(x,y,z)==n的 (x,y,z) 对数;G(n) 表示满足 n | gcd(x,y,z) 的(x,y,z)对数,即 gcd(x,y,z)%n==0 的(x,y,z) 对数;
由定义:G(n)=sigma(F(d)),F(n)=sigma(U(d/n)*G(d))
这题就是求F(1)。G(d)=(n/d)*(n/d)(n/d)。
当3个坐标为0时有0个点;
2坐标为0的时候可见点在三条坐标轴上一共3个;
1坐标为0的时候3*ans(ans=sigma(u(d)*(n/i)*(n/i)));
坐标都不为0的时候ans=ans=sigma(u(d)*(n/i)*(n/i)*(n/i))
提示:提交代码时不能用__int64,只能用long long
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 6 typedef __int64 LL; 7 const int maxn=1000005; 8 int prime[maxn],mu[maxn],num; 9 bool flag[maxn];10 11 void init()12 {13 int i,j;num=0;mu[1]=1;14 memset(flag,true,sizeof(flag));15 for(i=2;i<maxn;i++)16 {17 if(flag[i])18 {19 prime[num++]=i;mu[i]=-1;20 }21 for(j=0;j<num&&prime[j]*i<maxn;j++)22 {23 flag[i*prime[j]]=false;24 if(i%prime[j]==0)25 {26 mu[i*prime[j]]=0;break;27 }28 else mu[i*prime[j]]=-mu[i];29 }30 }31 }32 33 int main()34 {35 init();36 int t,i,n;37 scanf("%d",&t);38 while(t--)39 {40 scanf("%d",&n);41 LL ans=3;42 for(i=1;i<=n;i++)43 ans+=(LL)mu[i]*(n/i)*(n/i)*(n/i+3);44 printf("%I64d\n",ans);45 }46 return 0;47 }