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; }