题意:求两个点(x,y,z)的连线不经过其他点有几个
解:即为求GCD(x,y,z)为1的点有几个
解一:因为x,y,z均在1~n内,所以可以用欧拉函数解出
解二:莫比乌斯反演
设f[n]为GCD(x,y,z)=n的个数
设F[b]为b|GCD(x,y,z)的个数,很明显F[b]=(n/i)*(n/i)*(n/i)
所以F[n]=sigema(b|n,f[b]);
f[n]=sigema(n|b,mu[n],F[n])
#include <stdio.h> #include <string.h> const int maxn=1000005; int prime[maxn]; int num[maxn]; int mu[maxn]; void mobius() { memset(num,0,sizeof(num)); mu[1]=1; int all=0; for(int i=2;i<maxn;i++) { if(!num[i]) { prime[all++]=i; mu[i]=-1; } for(int j=0;j<all&&i*prime[j]<maxn;j++) { num[i*prime[j]]=1; if(i%prime[j]) mu[i*prime[j]]=-mu[i]; else { mu[i*prime[j]]=0; break; } } } return ; } int main() { int t; int n; long long sum; mobius(); while(scanf("%d",&t)!=-1) { while(t--) { sum=3; //x,y,z轴 scanf("%d",&n); for(int i=1;i<=n;i++) { sum+=(long long)mu[i]*(n/i)*(n/i)*((n/i)+3); //在面上的点,所以+3 } printf("%lld\n",sum); } } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-11-08 23:23:50