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; }


浙公网安备 33010602011771号