题解:
由题意可知,从左下角的点到其他所有点连成的不同斜率的边数即为所求。要求得边长 y / x 不同的数量( y < x),则求与 x 互质的数的个数 *2+3 即可(因为只求出了一个三角形的答案数量,需要*2来求正方形矩阵的答案数量,+3是有三个特殊的边,即两条 y / x == 0 以及一条 y / x == 1)。由于边长为 n 的边的答案包含了边长为 n - 1 的边的答案,所以求个前缀和即可。最后由于他给的是点数,所以求出的前缀和下标必须减一(点数比边长多一)。
代码:
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <bitset>
using namespace std;
typedef long long ll;
#define int ll
#define INF 0x3f3f3f3f3f3f3f3f
#define MAXM 200000 + 10
#define MAXN 40000 + 10
const ll mod = 1e9 + 7;
#define P pair<int, int>
#define fir first
#define sec second
int n;
int phi[MAXN];
int prime[MAXN], judge[MAXN], cnt;
void euler()
{
phi[1] = 0;
for(int i = 2; i < MAXN; i ++) {
if(!judge[i]) {
prime[++cnt] = i;
phi[i] = i - 1;
}
for(int j = 1; j <= cnt && prime[j] * i < MAXN; j ++) {
judge[i*prime[j]] = 1;
if(i % prime[j] == 0) {
phi[i*prime[j]] = phi[i] * prime[j];
break;
}
else phi[i*prime[j]] = phi[i] * phi[prime[j]];
}
}
phi[1] = 0;
for(int i = 2; i < MAXN; i ++) {
phi[i] += phi[i-1];
}
}
signed main()
{
euler();
cin >> n;
if(n == 1) cout << 0 << endl;
else cout << (phi[n-1] * 2 + 3)<< endl;
}
/*
The WAM is F**KING interesting .
*/