http://www.spoj.com/problems/VLATTICE/
明显,当gcd(x,y,z)=k,k!=1时,(x,y,z)被(x/k,y/k,z/k)遮挡,所以这道题要求的是gcd(x,y,z)==1的个数+{(x,y,0)|gcd(x,y)==1}的个数+3{(0,0,1),(0,1,0),(1,0,0)}
现在不去管最后的三个坐标轴上的点,
设f(i)=|{(x,y,0)|gcd(x,y)==i}|*3+|{(x,y,z)|gcd(x,y,z)==i}|,也就是不在坐标轴上且非0坐标值的最大公约数为n的个数,
设F(i)为由能被i整除的坐标值组成的不在坐标轴上的坐标的个数,则F(i)=n/i*n/i*(n/i+3),同时显然F(i)=sigma(b|n,f[i]),
由莫比乌斯反演,可得f(1)=sigma(mul(i)*F(i))
#include <cstdio> #include <algorithm> using namespace std; const int maxn =1e6+2; bool ifprime[maxn]; int mul[maxn]; int prime[maxn]; void moblus(){ ifprime[2]=true; for(int i=3;i<maxn;i+=2)ifprime[i]=true; int pnum=0; mul[1]=1; for(int i=2;i<maxn;i++){ if(ifprime[i]){ prime[pnum++]=i; mul[i]=-1; } for(int j=0;j<pnum&&i*prime[j]<maxn;j++){ ifprime[i*prime[j]]=false; if(i%prime[j]==0){ mul[i*prime[j]]=0; break; } else { mul[i*prime[j]]=-mul[i]; } } } } int main(){ int T; moblus(); scanf("%d",&T); while(T--){ int n; scanf("%d",&n); long long ans=3; for(int i=1;i<=n;i++){ ans+=(long long)mul[i]*(n/i)*(n/i)*(n/i+3); } printf("%I64d\n",ans); } return 0; }
时间: 2024-10-20 17:54:07