您的位置:首页 > 其它

poj 3090 Visible Lattice Points

2012-07-18 17:40 246 查看
先画一条(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;
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;
}

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: