定义:欧拉函数表示1-N中与N互质的数的个数;
欧拉函数用希腊字母φ表示,φ(N)表示N的欧拉函数.
欧拉函数性质:
1.欧拉函数是积性函数(非完全);
积性函数:对于任意互质的整数a和b有性质f(ab)=f(a)f(b)的数论函数。
完全积性函数:对于任意整数a和b有性质f(ab)=f(a)f(b)的数论函数。
2.除了N=2,φ(N)都是偶数;
3.当N为奇数时,φ(2*N)=φ(N);
4.若N是质数p的k次幂,φ(N)= 因为除了p的倍数之外,其他数都与N互质;
5.当N是质数时,φ(N)=N-1;
若将N表示成质因子分解式
所以我们有
φ(N)=N*(1-1/P1)(1-1/P2)…*(1-1/Pn).
公式注解:
互质是指两个或多个整数的公因数只有1的自然数。
若n = p^k,p为质数,k是正整数。
因为p是质数,所以1~p^k中与p^k有公因数的(不互质)都是p的倍数。(p,2p,3p....)
要计算整数 n 中有多少个 x 的倍数,可以使用以下简单的数学公式:
因此p^k中共有 个p的倍数,即
个与
不互质的数。故φ(n) = p^k - p^(k-1) = p^k(1 - 1/p)。 (总数 - 不互质的数 = 互质的数)
如果 n 有多个不同的质因数,即 n = p1^k1 * p2^k2 * ... * pm^km,那么可以使用以下公式计算:
φ(n) =p1^k1(1-1/p1) * p2^k2(1-1/p2) * ......* pm^km(1-1/pm)
=p1^k1 * p2^k2 * ... * pm^km * (1-1/p1) *(1-1/p2) *.....* (1-1/pm)
= n *(1-1/p1) *(1-1/p2) *.....* (1-1/pm)
例题:
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
int n;
int f(int x)
{
int rec=x;
for(int i=2;i*i<=x;i++)
{
if(x%i==0)
{
rec=rec/i*(i-1);//不能是/=
while(x%i==0)
x/=i;
}
}
if(x>1)rec=rec/x*(x-1);//不能是/=
return rec;
}
int main() {
ios::sync_with_stdio(false);
cout.tie(0);
int T;
cin>>T;
for(int t=1;t<=T;t++)
{
cin>>n;
int cnt=0;
for(int i=0;i<=n;i++)
{
cnt+=f(i);
}
cout<<t<<" "<<n<<" "<<cnt*2+1<<endl;
}
return 0;
}
例题:
此题数据量很大,所以要用到线性筛法求欧拉函数。
在线性筛法中,每个合数n只会被它的最小质因子p筛一次。我们恰好可以在此时执行以上两条判断,从phi(n/p)递推到phi(n)
1: primes[j]是i的最小质因子
2:primes[j] 不是i的最小质因子
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
const int N = 1e7+10;
int n;
int prime[N],cnt;
bool vis[N];
ll phi[N],sum[N];
void init(int n)
{
// phi[1]=1;
for(int i=2;i<=n;i++)
{
if(!vis[i])
{
prime[++cnt]=i;
phi[i]=i-1; // 1~i-1 都与 i 互质
}
for(int j=1;j<=cnt&&i*prime[j]<=n;j++)
{
vis[i*prime[j]]=true;
if(i%prime[j]==0) // primes[j]是i的最小质因子
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
phi[i*prime[j]]=phi[i]*(prime[j]-1); //i % primes[j] != 0: primes[j]不是i的质因子
}
}
for(int i=1;i<=n;i++)
sum[i]=sum[i-1]+phi[i];
}
int main() {
ios::sync_with_stdio(false);
cout.tie(0);
cin>>n;
init(n);
ll res=0;
for(int i=1;i<=cnt;i++)
{
int p=prime[i];
res+=sum[n/p]*2+1;
}
cout<<res<<endl;
return 0;
}
题目解析:
知道这个公式后,这道题就很简单了。 我们直接用 1 ~ n - 1 的和减去 n * φ(n) / 2 就能得到答案。
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
const int mod = 1000000007;
int n;
int eular(int n)
{
int rec = n;
for(int i = 2; i <= n / i; i++)
{
if(n % i == 0)
{
rec = rec / i * (i - 1);
while(n % i == 0) n /= i;
}
}
if(n > 1) rec = rec / n * (n - 1);
return rec;
}
signed main() {
ios::sync_with_stdio(false);
cout.tie(0);
while(cin >> n, n)
{
cout << ( n * (n - 1) / 2 - eular(n) * n / 2 ) % mod << endl;
}
return 0;
}