定义:欧拉函数表示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).
例题:
#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;
}