Acwing 201 可见的点

题意:

在一个平面直角坐标系的第一象限内,如果一个点$(x, y)$与点$(0, 0)$的连线中没有通过任何点,则该点在原点处是可见的。计算给定整数$n$下,满足$0 \leq x, y \leq n$的可见点的数量

思路:

每一条光线都是直线$y = kx$, 设每条线的第一个点为$(x_0, y_0)$,得$y = \frac{y_0}{x_0}x$,$\frac{y_0}{x_0}$为最简分数,则$(x_0, y_0)$互质,求有多少个数对满足$(x_0, y_0)$互质即可。特判$y = x, y = 0, x = 0$后,只要算$[2, n]$的欧拉函数的和即可。由于数对关于$y = x$对称,求得欧拉函数的和$*2+3$即为答案

Code:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 1e3 + 10;

#define sd(a) scanf("%d", &a)

int primes[N], cnt, phi[N], sum[N];
bool st[N];

void get(int n){
    phi[1] = 1;
    sum[1] = 0;
    for(int i = 2; i <= n; i ++){
        if(!st[i]){
            primes[cnt ++] = i;
            phi[i] = i - 1;
        }
        sum[i] = sum[i - 1] + phi[i];
        for(int j = 0; primes[j] <= n / i; j ++){
            st[i * primes[j]] = true;
            if(i % primes[j] == 0){
                phi[i * primes[j]] = primes[j] * phi[i];
                break;
            }
            phi[i * primes[j]] = (primes[j] - 1) * phi[i]; 
        }
    }
}

void solve(){
    int n;
    sd(n);
    
    printf("%d %d\n", n, 2 * sum[n] + 3);
}

int main(){
    int t;
    sd(t);
    
    get(N - 10);
    int tt = 1;
    while(t --){
        cout << tt ++ << " ";
        solve();
    }
    
    return 0;
}

 

posted @ 2020-08-01 21:41  君顾  阅读(117)  评论(0编辑  收藏  举报