1~
N中与
N互质的数的个数被成为欧拉函数,记为
φ(N)。
在算数基本定理中,
N=p1c1p2c2...pmcm(∀pi皆为质数)则:
φ(N)=N∗(p1p1−1)∗(p2p2−1)∗......∗(pmpm−1)=N∗质数p∣N∏(1−p1)
证明:设
p,q是
N的质因子,则
1~
N中p,q的倍数为
p,2p,3p,.......,N/p,q,2q,3q,......,N/q(pq的倍数被筛了2遍)
共有
N/p+N/q−N/pq个(由算数基本定理可知,
pq一定
≤N),则
1~
N中不与
N含有共同质因子
p或
q的数的个数为:
N−(pN)−(qN)+(pqN)=N∗(1−p1−q1+pq1)=N(1−p1)(1−q1)
推广到多种情况(全部质因子),用数学归纳法证明即可。
证毕。
欧拉函数性质
-
∀n>1,1~
n中与n互质的数的和为
n/2∗φ(n)
证明:
∵与n互质的x,gcd(n,x)=gcd(n,n−x),∴与n互质的x,n−x成对出现,平均值为n/2.因此与n互质的数的平均值也为n/2,证毕。
-
若a,b互质,则
φ(ab)=φ(a)φ(b)
证明:
∵φ(a)=a∗∏质数p∣a(1−p1),φ(b)=b∗∏质数p∣b(1−p1),φ(ab)=ab∗∏质数p∣ab(1−p1)=ab∗∏质数p∣a(1−p1)∗∏质数p∣b(1−p1),由于两数互质,无公共质因子。证毕。
依照性质2,可得积性函数。
-
若
f是积性函数,且在算术基本定理中
n=∏i=1mpici,根据积性函数定义式可得。
-
若
p∣n且
p2∣n,则
φ(n)=φ(n/p)∗p
证明:
φ(n)=n∗∏质数w∣n(1−w1)=(n/p)∗∏质数w∣n/p(1−w1)∗p=φ(n/p)∗p,由于
n/p与
n所含质因子相同,只是
p的指数不同罢了,所以等式成立。
-
若
p是质数,p∣n且
p2∤n,则
φ(n)=φ(n/p)∗(p−1)
证明:
∵n/p与p互质,则φ(n)=φ(n/p)∗φ(p)=φ(n/p)∗(p−1)
-
∑d∣nφ(d)=n
证明:
设f(n)=∑d∣nφ(d),f(m)=∑d∣mφ(d),
若n,m互质,φ是积性函数,
f(nm)=∑d∣nmφ(d)=∑d∣nφ(d)∗∑d∣mφ(d)=f(n)∗f(m),
即∑d∣nφ(d)是积性函数,对于单个质因子,f(pm)=φ(1)+φ(p)+φ(p2)+......+φ(pm)根据性质4,我们可以发现
f(pm)为等比数列求和+1,即
f(pm)=1+(1−pp−1−(p−1)∗pm)=pm.所以
f(n)=i=1∏mf(pici)=i=1∏mpici=n性质6成立.
题目描述
φ(x)表示小于或等于x的正整数中与n互质的数的数目。。
有n次询问,每次问
φ(x)的值。
【输入格式】
第一行
n(
1<=n<=10000)
下来n行,每行一个整数x,表示求
φ(x)。(
1<=x<=20000000)
【输出格式】
每次询问输出一行一个整数
φ(x)。
【样例输入】
3
10
20
100
【样例输出】
4
8
40
代码
1.运用性质4、5
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
const int N=1270608;
const int M=2e7+10;
const int inf=2e7;
int prime[N],phi[M],m;
bool v[M];
void g_p()
{
m=0;
memset(v,true,sizeof(v));
for(int i=2;i<=inf;i++)
{
if(v[i])prime[++m]=i,phi[i]=i-1;
for(int j=1;j<=m&&i*prime[j]<=inf;j++)
{
v[i*prime[j]]=false;
if(i%prime[j]==0)
{
phi[i*prime[j]]=prime[j]*phi[i];
break;
}
else
{
phi[i*prime[j]]=(prime[j]-1)*phi[i];
}
}
}
}
int main()
{
g_p();int n;scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int x;scanf("%d",&x);
printf("%d\n",phi[x]);
}
return 0;
}
2.运用欧拉函数定理
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
using namespace std;
const int N=2e7+10;
int a[N];
inline int solve(int x)
{
int d=x,dd=x;
for(int i=2;i*i<=x;i++)
{
if(x%i==0)
{
d=d/i*(i-1);
while(!(x%i))
{
x/=i;
}
}
}
int last=0;
if(x>1)d=d/x*(x-1);a[dd]=d;
return d;
}
int main()
{
int n;scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int x;scanf("%d",&x);
printf("%d\n",!a[x-1]?solve(x-1):a[x-1]);
}
return 0;
}