POJ 3090 Visible Lattice Points (ZOJ 2777)

题目

输入n,问从坐标(0,0)点能看到多少点,点的坐标范围是0<=(x,y)<=n
只有一个点没有被另一个点挡住才能看到。
如上图,n=5的时候,能看到21个点

Input

第一行输入t,表示样例个数。1<=t<=1000 接下来t行,每行输入一个正整数n 。 1<=n<=1000

Output

输出n行三列。

第一列从1到n表示第i个样例,第二列输出n,第三列输出能看到的点的个数

题解

过原点能做几条范围在n内的过整数点的线,定点做线的区分是斜率,所以问题再次转换为,求整点斜率的问题。

数据范围不大,n<=1000,说明O(n^2)复杂度的方法或许可行,但查询t<=1000,如果要使用,O(n^2)的需要预先处理,这题求出n的数的同时也会求出1~n-1的数所以很容易预先打表。

可以使用stl的map容器进行对斜率的唯一标识,来暴力计算斜率个数。

也可以使用gcd来判断gcd是否是1来唯一标识,来暴力计算斜率个数。

但map判断会超时

AC代码

#include<iostream>

using namespace std;

int gcd(int a, int b) {
    return b == 0 ? a : gcd(b, a%b);
}
const int max_n = 1000;
int b[max_n+5];

int main() {
    int T, n;
    scanf("%d", &T);
    int ans = -1;//因为下面的判断当i==j时会判断两次,所以减1
    for (int i = 1; i <= max_n; i++) {
        
        for (int j = 0; j <= i; j++) {
            if (gcd(i, j) == 1)ans++;
            if (gcd(j, i) == 1)ans++;
        }
        b[i] = ans;
    }


    for (int t = 1; t <= T; t++) {
        scanf("%d", &n);
        printf("%d %d %d
",t,n,b[n]);
    }


    return 0;
}
原文地址:https://www.cnblogs.com/komet/p/13873511.html