这道题是一道欧拉函数的例题,但由于欧拉函数覆盖的数学前置知识有亿点多。
所以建议自行看前置知识:欧几里得+扩展欧几里得、中国剩余定理、积性函数(只用记住定义就行)
当然你也可以看一看 oi-wiki 上的欧拉函数但我们这里还是会讲的。
欧拉函数
定义: φ ( n ) \varphi(n) φ(n) 表示 1 ∼ n 1\sim n 1∼n 中与 n n n 互质的数即 1 ≤ t ≤ n , gcd ( n , t ) = 1 1\le t\le n,\gcd(n,t)=1 1≤t≤n,gcd(n,t)=1 欧拉函数是一个积性函数即 n , m ∈ N + , n ⊥ m , φ ( n ) φ ( m ) = φ ( n m ) n,m\in \N^+,n\bot m,\varphi(n)\varphi(m)=\varphi(nm) n,m∈N+,n⊥m,φ(n)φ(m)=φ(nm)
证明:我们先设 x 1 , x 2 , . . . , x φ ( n ) x_1,x_2,...,x_{\varphi(n)} x1,x2,...,xφ(n) 是与 n n n 互质的数, y 1 , y 2 , . . . , y φ ( m ) y_1,y_2,...,y_{\varphi(m)} y1,y2,...,yφ(m) 是与 m m m 互质的数, z 1 , z 2 , . . . , z φ ( n m ) z_1,z_2,...,z_{\varphi(nm)} z1,z2,...,zφ(nm) 是与 n m nm nm 互质的数。
根据中国剩余定理,由于 n ⊥ m n\bot m n⊥m,存在唯一的 1 ≤ z ≤ n m 1\le z\le nm 1≤z≤nm 满足 { z ≡ x i ( m o d n ) z ≡ y j ( m o d m ) \begin{cases}z\equiv x_i\pmod n\\z\equiv y_j\pmod m\end{cases} {z≡xi(modn)z≡yj(modm) 并且由于 x i ⊥ n , y j ⊥ m x_i\bot n,y_j \bot m xi⊥n,yj⊥m 所以 z ⊥ n , z ⊥ m z\bot n,z\bot m z⊥n,z⊥m 也就是说 z ⊥ n m z\bot nm z⊥nm 那么对于某一组 ( x i , y j ) (x_i,y_j) (xi,yj) 肯定有一个(根据中国剩余定理)唯一的解 z k z_k zk 与它们相对且每组 ( x i , y j ) (x_i,y_j) (xi,yj) 是互不相同的。
证毕。
变式:
我们易知 p p p 是质数 φ ( p k ) = p k − p k − 1 = p k ( 1 − 1 p ) \varphi(p^k)=p^k-p^{k-1}=p^k(1-\frac{1}{p}) φ(pk)=pk−pk−1=pk(1−p1)
n = p 1 k 1 p 2 k 2 . . . p d k d , φ ( n ) = n ( 1 − 1 p 1 ) ( 1 − 1 p 2 ) . . . ( 1 − 1 p d ) n=p_1^{k_1}p_2^{k_2}...p_d^{k_d},\varphi(n)=n(1-\frac{1}{p_1})(1-\frac{1}{p_2})...(1-\frac{1}{p_d}) n=p1k1p2k2...pdkd,φ(n)=n(1−p11)(1−p21)...(1−pd1)
做题思路
做这道题时,我也是看了题解,发现大佬们都说只要
x
⊥
y
x\bot y
x⊥y 就能被看见,左下角是
(
0
,
0
)
(0,0)
(0,0),当然还有几个特殊情况,后面慢慢说
画红圈的地方都是特殊情况,特殊情况先不考虑,先考虑不是特殊情况
我们先考虑点
(
9
,
3
)
(9,3)
(9,3) 它的
gcd
(
x
,
y
)
=
3
\gcd(x,y)=3
gcd(x,y)=3 那么我们就分成三段,第一段是点
(
9
,
3
)
(9,3)
(9,3) 到点
(
6
,
2
)
(6,2)
(6,2),第二段是点
(
6
,
2
)
(6,2)
(6,2) 到点
(
3
,
1
)
(3,1)
(3,1),第三段是点
(
3
,
1
)
(3,1)
(3,1) 到点
(
0
,
0
)
(0,0)
(0,0) 我们可以发现,这三段是一毛一样的,而且都是由第三段复制平移的,因此,它们的角度是不变的,所以,我们可以将此题改成:点
(
x
,
y
)
(x,y)
(x,y) 被
(
x
−
gcd
(
x
,
y
)
,
y
−
gcd
(
x
,
y
)
)
(x-\gcd(x,y),y-\gcd(x,y))
(x−gcd(x,y),y−gcd(x,y)) 挡住了,因此,只要
(
x
,
y
)
(x,y)
(x,y) 的
gcd
(
x
,
y
)
=
1
\gcd(x,y)=1
gcd(x,y)=1 即
x
⊥
y
x\bot y
x⊥y 就行。
现在我们就要考虑,怎样才能求出。
我们只需要分成两部分,因为我们发现他是对称的。
代码:
#include<bits/stdc++.h>
#define all(x) x.begin(),x.end()
#define ll long long
#define ull unsigned long long
#define db double
#define x first
#define y second
#define fast ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);
#define endl '\n'
#define pb push_back
#define swap(a,b) a=a^b,b=a^b,a=a^b
#define mem(x,a) memset(x,a,sizeof(x))
#define rep(l,r,i) for(int i=l,END##i=r;i<=END##i;i++)
#define per(r,l,i) for(int i=r,END##i=l;i>=END##i;i--)
#define sc scanf
#define pr printf
#define pii pair<int,int>
#define pll pair<ll,ll>
#define vi vector<int>
using namespace std;
const int N=40010;
int phi[N],p[N],cnt;
bitset<N>vis;
int main(){
ll ans=0;
int n;cin>>n;
phi[1]=1;
rep(2,n,i){
if(!vis[i])p[++cnt]=i,phi[i]=i-1;
for(int j=1;p[j]<=n/i;j++){
vis[p[j]*i]=true;
if(i%p[j]==0){
phi[p[j]*i]=phi[i]*p[j];
break;
}
phi[p[j]*i]=phi[i]*phi[p[j]];
}
}
rep(1,n-1,i)
ans+=phi[i];
printf("%lld\n",n==1?0:ans*2+1);
return 0;
}