• spoj 7001. Visible Lattice Points GCD问题 莫比乌斯反演


    SPOJ Problem Set (classical)

    7001. Visible Lattice Points

    Problem code: VLATTICE

    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 : 




     
    Sample Output : 

    19 
    175 
     
    Constraints : 
    T <= 50 
    1 <= N <= 1000000

    题意:GCD(a,b,c)=1,   0<=a,b,c<=N ;

    莫比乌斯反演,十分的巧妙。

    GCD(a,b)的题十分经典。这题扩展到GCD(a,b,c)加了一维,但是思想却是相同的。

    设f(d) = GCD(a,b,c) = d的种类数 ; 

      F(n) 为GCD(a,b,c) = d 的倍数的种类数, n%a == 0 n%b==0 n%c==0。

      即 :F(d) = (N/d)*(N/d)*(N/d);

    则f(d) = sigma( mu[n/d]*F(n), d|n )

    由于d = 1 所以f(1) = sigma( mu[n]*F(n) ) = sigma( mu[n]*(N/n)*(N/n)*(N/n) );

    由于0能够取到,所以对于a,b,c 要讨论一个为0 ,两个为0的情况 (3种).

     1 #include<iostream>
     2 #include<stdio.h>
     3 #include<cstring>
     4 #include<cstdlib>
     5 using namespace std;
     6 
     7 typedef long long LL;
     8 const int maxn = 1000000+3;
     9 bool s[maxn];
    10 int prime[maxn],len = 0;
    11 int mu[maxn];
    12 void  init()
    13 {
    14     memset(s,true,sizeof(s));
    15     mu[1] = 1;
    16     for(int i=2;i<maxn;i++)
    17     {
    18         if(s[i] == true)
    19         {
    20             prime[++len]  = i;
    21             mu[i] = -1;
    22         }
    23         for(int j=1;j<=len && (long long)prime[j]*i<maxn;j++)
    24         {
    25             s[i*prime[j]] = false;
    26             if(i%prime[j]!=0)
    27                 mu[i*prime[j]] = -mu[i];
    28             else
    29             {
    30                 mu[i*prime[j]] = 0;
    31                 break;
    32             }
    33         }
    34     }
    35 }
    36 
    37 int main()
    38 {
    39     int n,T;
    40     init();
    41     scanf("%d",&T);
    42     while(T--)
    43     {
    44         scanf("%d",&n);
    45         LL sum = 3;
    46         for(int i=1;i<=n;i++)
    47             sum = sum + (long long)mu[i]*(n/i)*(n/i)*3;
    48         for(int i=1;i<=n;i++)
    49             sum = sum + (long long)mu[i]*(n/i)*(n/i)*(n/i);
    50         printf("%lld
    ",sum);
    51     }
    52     return 0;
    53 }
  • 相关阅读:
    整数数组中最大子数组的和的问题(续)
    整数数组中最大子数组的和的问题
    PHP开发环境(Apache+mysql+PHPstorm+php)的搭建
    echart 库 初始
    2.15 学习总结 之 天气预报APP volley(HTTP库)之StringRequest
    2.14 学习总结 之 序列化
    2.13 阶段实战 使用layui重构选课系统
    2.12 学习总结 之 表单校验插件validate
    jsp连接数据库的乱码问题 servlet请求参数编码处理get post
    Rocket
  • 原文地址:https://www.cnblogs.com/tom987690183/p/3933335.html
Copyright © 2020-2023  润新知