欧拉函数 get !
欧拉函数,也叫
证明就不写了,什么中国剩余定理什么的真让人头大
欧拉函数有两个性质:
-
φ$ 函数是积性函数,即 $φ ( m \times n ) = φ ( m ) \times φ ( n ) -
如果
n 为奇数,φ ( 2n ) = φ ( n )
模板:
//线性筛欧拉函数
int vis[MAXN],phi[MAXN],prime[MAXN];
int tot;//vis 为确定是否是素数,tot是素数个数
void Euler_Phi()
{
phi[1] = 1;
for(int i=2;i<=n;i++)
{
if(!vis[i])
{
phi[i] = i-1;
prime[++tot] = i;
}
for(int j=1;j<=tot && prime[j]*i<=n;j++)
{
int mul = i*prime[j];
vis[mul] = 1;
if(i%prime[j] == 0)
{
phi[mul] = phi[i]*prime[j];
break;
}
else
phi[mul] = phi[i]*(prime[j]-1);
}
}
}
//单个数的欧拉函数
int euler_Phi(int n)
{
int m = (int)sqrt(n+0.5);
int ans = n;
for(int i=2;i<=m;i++)
if(n%i == 0)
{
ans = ans/i*(i-1); //先做除法,防止爆 int
while(n%i == 0) n /= i;
}
if(n > 1) ans = ans/n*(n-1);
return ans;
}
试炼:
传送门
由题意可以发现,只有斜率不同时,才能连线
所以对于一个点
那么就可以连线,所以要找的就是互质的两个数
就可以使用欧拉函数了
可以先算上半个三角形的答案,再乘 2 加 3 (垂直的两个和对角线上的一个)
这样就可以用线性筛欧拉函数了
int m[MAXN],phi[MAXN],prime[MAXN];
// m 为小于 i 的最小质数
void Euler_Phi()
{
m[1] = 1;
for(int i=2;i<n;i++)
{
if(!m[i])
{
prime[++tot] = i;
phi[i] = i-1;
m[i] = i;
}
for(int j=1;j<=tot && prime[j]*i<=n;j++)
{
int k = prime[j]*i;
m[k] = prime[j];
if(m[i] == prime[j])
phi[k] = phi[i]* prime[j];
else phi[k] = phi[i]*(prime[j]-1);
//运用了函数的积性
}
}
}
int main(void)
{
cin >> n;
if(n == 1)
{
cout << "0";
return 0;
}
Euler_Phi();
for(int i=1;i<n;i++) ans += phi[i];
cout << ans*2+3;
return 0;
}