您的位置:首页 > 其它

Visible Lattice Points POJ - 3090

2017-08-07 15:34 246 查看
题意:

有一个n*n的点阵,站在(0,0)点,你可以看见(1,1),(1,2),但是你看不见(2,2),(2,4)

因为(2,2)会被(1,1)挡住,(2,4)会被(1,2)挡住

给定n,求能看见的点的个数

思路:

即在n*n范围内,gcd(i,j)=1的数对的个数

想到欧拉函数是[1,n-1]内与n互质的数的个数,

前缀加和

#include<stdio.h>
#include<string.h>
int a[1009];
bool book[1009];
int p[1009];
int ans[1009];
void init()
{
int i;
for(i=1; i<=1009; i++)
p[i]=i;
for(i=2; i<=1009; i+=2)
p[i]/=2;
for(i=3; i<=1009; i+=2)
if(p[i]==i)
{
for(int j=i; j<=1009; j+=i)
p[j]=p[j]/i*(i-1);
}
ans[0]=0;
ans[1]=3;
for(int i=2;i<=1009;i++)
ans[i]=ans[i-1]+2*p[i] ;
}
int main()
{

int t,n;
init();
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
scanf("%d",&n);
printf("%d %d %d\n",i,n,ans
);
}

return 0;
}

另外这也可以用莫比乌斯反演

我们要求出gcd(a,b)=1的数对个数

F(1)= sigma f(1*k)

f(1)= sigma u(d/1) * f(d*k);

#include<stdio.h>
#include<string.h>
const int MAXN=1000;
bool check[MAXN+10];
int prime[MAXN+10];
int mu[MAXN+10];
void init()
{
memset(check,false,sizeof(check));
mu[1] = 1;
int tot = 0;
for(int i = 2; i <= MAXN; i++)
{
if( !check[i] )
{
prime[tot++] = i;
mu[i] = -1;
}
for(int j = 0; j < tot; j++)
{
if(i * prime[j] > MAXN) break;
check[i * prime[j]] = true;
if( i % prime[j] == 0)
{
mu[i * prime[j]] = 0;
break;
}
else
{
mu[i * prime[j]] = -mu[i];
}
}
}
}
int main()
{

int t,n;
init();
scanf("%d",&t);
for(int j=1;j<=t;j++)
{
scanf("%d",&n);
int ans=2;
for(int i=1;i<=n;i++)
ans+=(long long)mu[i]*(n/i)*(n/i); //莫比乌斯反演 F(i)=(n/i)*(n/i)*(n/i+3) f(i)=sigma F(k*i);
printf("%d %d %d\n",j,n,ans);
}
return 0;
}


总结一下:通过这个题目和  GCD HDU - 2588 都可以看到 某些时间 欧拉函数也完成了容斥的工作
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: