可见的点
可见的点
在一个平面直角坐标系的第一象限内,如果一个点 与原点 的连线中没有通过其他任何点,则称该点在原点处是可见的。
例如,点 就是不可见的,因为它与原点的连线会通过点 。
部分可见点与原点的连线如下图所示:
编写一个程序,计算给定整数 的情况下,满足 的可见点 的数量(可见点不包括原点)。
输入格式
第一行包含整数 ,表示共有 组测试数据。
每组测试数据占一行,包含一个整数 。
输出格式
每组测试数据的输出占据一行。
应包括:测试数据的编号(从 开始),该组测试数据对应的 以及可见点的数量。
同行数据之间用空格隔开。
数据范围
输入样例:
4 2 4 5 231
输出样例:
1 2 5 2 4 13 3 5 21 4 231 32549
解题思路
题目等价于问从处射处一条光线,能够射到多少个点?其中,当一条光线射到一个点后会把后面的点都挡住。
由于光线都从处射出,因此每一条直线可以看成,因此所有的点都会在某一条直线上。而如果一个点能够被射到,此时所在的直线为,那么意味着是这条直线上的第一个点(该点的左下方不存在在同一条直线上的点),等价于与互质。假设与不互质,,那么也在直线上且在的左下方,即会被挡住,就矛盾了。
因此问题就变成了有多少个数对满足。
统计的方法是,先画出,很明显上的点都不满足条件,同时直线上下两个部分是对称的,下部分有多少个那么上部分就有多少个,因此这里只统计下部分的答案。从枚举每一列,首先第列中与互质的点有个,第列中与互质的点有个,第列中与互质的点有个,以此类推。也就是对于第列求中与互质的数有多少个,这就是欧拉函数。因此最终答案就是,加是加上对角线上这个点。
AC代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int N = 1010; 5 6 int primes[N], cnt; 7 bool vis[N]; 8 int phi[N]; 9 10 void get_prime(int n) { 11 phi[1] = 1; 12 for (int i = 2; i <= n; i++) { 13 if (!vis[i]) primes[cnt++] = i, phi[i] = i - 1; 14 for (int j = 0; primes[j] <= n / i; j++) { 15 vis[primes[j] * i] = true; 16 if (i % primes[j] == 0) { 17 phi[primes[j] * i] = phi[i] * primes[j]; 18 break; 19 } 20 phi[primes[j] * i] = phi[i] * (primes[j] - 1); 21 } 22 } 23 } 24 25 int main() { 26 get_prime(N - 1); 27 int m; 28 scanf("%d", &m); 29 for (int u = 1; u <= m; u++) { 30 int n; 31 scanf("%d", &n); 32 int ret = 1; 33 for (int i = 1; i <= n; i++) { 34 ret += phi[i] * 2; 35 } 36 printf("%d %d %d\n", u, n, ret); 37 } 38 39 }
参考资料
AcWing 201. 可见的点(算法提高课):https://www.acwing.com/video/694/
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/17063959.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效