AcWing 201. 可见的点

AcWing 201. 可见的点

题意:

在这里插入图片描述

题解:

我们先说结论:坐标(i,j),如果i和j互质,说明该坐标为可见
为什么?
我们想想什么样的坐标可见,什么样的会被挡住。光线是一个直线,在同一个直线上的点会被第一个点挡住,而所有光都从一个地方出发,也就是如果斜率一样,后面会被前面的挡住(暂时不考虑斜率不存在的情况)。对于坐标(i,j),斜率为k=i/j,如果i和j不互质,设gcd(i,j)=d,那么(i/d)/(j/d)也等于k,且(i/d,j/d)要比(i,j)小,前者会挡住后缀,这说明了i和j必须互质,不然会被更小的i/d和j/d给挡住
我们观察题目给的图形,图形是关于斜率为1的直线对称(也很好理解,x与y互质,那y也与x互质),因此我们只考虑下半部分
根据横坐标,我们依次查看,横坐标为1时,互质的点的数量为1,横坐标为2时,互质的数量为1…我们要找的是与横坐标互质,且小于横坐标的点的数量,这不就是欧拉函数吗
所有答案就是横坐标所对应的欧拉函数的和,乘2(因为我们只算了一半),加1(别忘了对称轴上还有一个点)
在这里插入图片描述

代码:

#include<bits/stdc++.h>
#define debug(a,b) printf("%s = %d\n",a,b);
typedef long long ll;
using namespace std;

inline int read(){
   int s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);
   return s*w;
}
const int maxn=5e4+9;
int prime[maxn],cnt;
bool st[maxn];
int phi[maxn];
void init(int n){
	phi[1]=1;
	for(int i=2;i<=n;i++){
		if(!st[i])
		{
			prime[cnt++]=i;
			phi[i]=i-1;
		}
			
		for(int j=0;prime[j]*i<=n;j++){
			st[prime[j]*i]=1;
			if(i%prime[j]==0)
			{
				phi[i*prime[j]]=phi[i]*prime[j];
				break;
			}
			phi[i*prime[j]]=phi[i]*(prime[j]-1);
		}
	}
}
int main()
{
	init(maxn-1);
	int n,m;
	cin>>m;
	for(int T=1;T<=m;T++){
		cin>>n;
		int res=1;//对角线那个 
		for(int i=1;i<=n;i++)res+=phi[i]*2;
		cout<<T<<" "<<n<<" "<<res<<endl; 
	}
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值