poj 3090 Visible Lattice Points

先画一条(0, 0)到(n, n)的线,把图分成两部分,两部分是对称的,只需算一部分就好。
取右下半,这一半里的点(x, y)满足x >= y
可以通过欧拉函数计算第k列有多少点能够连到(0, 0)
若x与k的最大公约数d > 1,则(0, 0)与(x, k)点的连线必定会通过(x/d, k/d),就被挡住了
所以能连的线的数目就是比k小的、和k互质的数的个数,然后就是欧拉函数。
方法一:
View Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<cstring>
#include<vector>
using namespace std;
bool G[1024][1024];
bool judge( int x , int y )
{
    if( x <= 1000  && y<=1000 ) return true;
    return false;    
}
void Get_map( )
{
    G[0][0] =true;
    for( int i = 0 ; i <= 1000 ; i++ )
    {
       for( int j = (i==0? 1 : 0) ; j <= 1000 ; j++ )
       {
           if( !G[i][j] )
           { 
                int tx = i - 0 ,ty = j - 0;
                int x = i , y = j;
                while( judge( x + tx , y + ty ) )
                {
                     x += tx ; y += ty;
                     G[x][y] = true;     
                }        
           }        
       }
    }
}
int Calculate( int n )
{
    int sum = 0;
    for( int i = 0 ; i <= n ; i++ )
    {
           for( int j  = 0 ; j <= n ; j++ )
              if( !G[i][j] ) sum ++;
    }    
    return sum;
}
int main(  )
{
    memset( G , 0 , sizeof(G ));
    Get_map(  );
    int Case , n;
    while( scanf( "%d",&Case )==1 )
    {
          for( int i = 1 ;i <= Case ; i ++ )
          {
              scanf( "%d",&n );
              printf( "%d %d %d\n",i,n,Calculate( n ) );
          }    
    }
    //system( "pause" );
    return 0;
}
方法二:
View Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<cstring>
#include<vector>
using namespace std;
bool G[1024][1024] = {0};
int Gcd( int a , int b )
{
   return b == 0 ? a : Gcd( b ,a%b );
}
void Get_map(  )
{
    int ans = 0;
    for( int i = 0 ; i <= 1000 ; i ++ )
    {
        for( int j = 0 ; j <= i ; j ++ )
        {
            if( Gcd( i , j )==1 )
            {
               G[i][j] = true;    
            }    
        }    
    }
}
int Calculate( int n )
{
    int ans = 0;
    for( int i = 0 ; i <= n ; i ++ )
    {
        for( int j = 0 ; j <= i ; j ++ )
        {
            if( G[i][j] )
            {
              ans++;    
            }    
        }    
    }
    return ans;
}
int main(  )
{
    Get_map( );
    int Case , n;
    while( scanf( "%d",&Case )==1 )
    {
          for( int i = 1 ;i <= Case ; i ++ )
          {
              scanf( "%d",&n );
              printf( "%d %d %d\n",i,n,Calculate( n )*2-1 );
          }    
    }
    //system( "pause" );
    return 0;
}

 

方法三:
容斥定理:
View Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<cstring>
#include<vector>
using namespace std;
class Node
{
public:
     int cnt,num[20];
}node[1024];
void Prime( )
{
    int prime[500],cnt=0;
    bool hash[1024] = {0};
    for( int i = 2 ;i <= 40 ; i ++ )
    {
         if( !hash[i] )
         {
             for( int j = 2 ;j*i <=1000; j ++ )
             hash[i*j] = true;        
         }    
    }    
    for( int i = 2 ;i <= 1000; i ++ )
         if( !hash[i] )  prime[cnt++] = i;
    for( int i = 1 ; i <= 1000; i ++ )
    {
        int t = i;
        node[i].cnt = 0;
        for( int j = 0 ; j < cnt ; j++ )
        {
             if(  prime[j] > t ) break;
             if( t % prime[j] == 0 )
             {
                  node[i].num[node[i].cnt++] = prime[j];
                  while( t % prime[j] == 0  )
                         t /= prime[j];
             }
        }    
    }
}
int DFS( int t , int n  , int k )
{
    int ans = 0;
    for( int i = t ; i < node[k].cnt ; i ++ )
         ans += n/node[k].num[i] - DFS( i + 1 , n/node[k].num[i] , k );
    return ans;     
}
int main(  )
{
    int Case,n;
    Prime();
    while( scanf( "%d",&Case )==1 )
    {
         for( int j = 1 ; j <= Case ; j ++ )
         {
              int ans = 0;
              scanf( "%d",&n );
              for( int i = 1 ; i <= n ; i ++  )
                   ans += n - DFS( 0, n , i );
             printf( "%d %d %d\n",j , n ,ans + 2 );
         }    
    }
    //system( "pause" );
    return 0;
}

 



posted @ 2012-07-18 17:40  wutaoKeen  阅读(161)  评论(0)    收藏  举报