SPOJ VLATTICE

来源:互联网 发布:伴奏制作软件 编辑:程序博客网 时间:2024/06/05 10:02

做此提前可以先做二维的:点击打开链接

题目链接:点击打开链接

题目大意:

有一个n*n*n的三维格点,问在原点(0,0,0)处能看到多少个格点?(n<=1000000,50组数据)
思路:


莫比乌斯反演!

什么是莫比乌斯反演?



求莫比乌斯的函数;

int prime[maxn],mu[maxn];bool unprime[maxn];long long  n;void moblus(){    int i,j,k = 0;    mu[1]=1;    for(i = 2; i <maxn; i++)    {        if(!unprime[i])        {            prime[k++] = i;mu[i] =-1;//此处处理phi(p)        }        for(j = 0; j < k && prime[j]*i <maxn; j++)        {            unprime[prime[j] *i] = true;            if(i % prime[j] != 0)            {                //p不是i的约数                mu[prime[j]*i] = -mu[i];//欧拉数加一 所以莫比乌斯数乘以-1            }            else            {                //p是i的约数  说明有两个相同的质数                mu[prime[j]*i] =0;                break;            }        }    }}




AC代码如下

#include <cstdio>#include <cstring>#include <algorithm>#include<iostream>#include<map>using namespace std;#define maxn  1000005#define mod 9901int prime[maxn],mu[maxn];bool unprime[maxn];long long  n;void moblus(){    int i,j,k = 0;    mu[1]=1;    for(i = 2; i <maxn; i++)    {        if(!unprime[i])        {            prime[k++] = i;mu[i] =-1;//此处处理phi(p)        }        for(j = 0; j < k && prime[j]*i <maxn; j++)        {            unprime[prime[j] *i] = true;            if(i % prime[j] != 0)            {                //p不是i的约数                mu[prime[j]*i] = -mu[i];//欧拉数加一 所以莫比乌斯数乘以-1            }            else            {                //p是i的约数  说明有两个相同的质数                mu[prime[j]*i] =0;                break;            }        }    }}int main(){    int t;    scanf("%d",&t);    moblus();    for(int cas=1;cas<=t;cas++){scanf("%lld",&n);long long  sum=3;for(int i=1;i<=n;i++)sum+=mu[i]*(n/i)*(n/i)*(n/i+3);printf("%lld\n",sum);}    return 0;}



原创粉丝点击