欧拉函数详解
欧拉函数
我们用phi(n)表示欧拉函数
定义:phi(n)表示对于整数n,小于等于n中与n互质的数的个数
性质
1.phi(n)为积性函数
证明:
此处证明需要用到下面计算方法1中的内容,建议先看后面再回过头来看这里
假设存在p,q,且p*q=n
将n,p,q进行质因数分解
n=a_1^{p_1}*a_2^{p_2}...*a_k^{p_k}
p=a_1^{p_1}*a_2^{p_2}...*a_m^{p_m}
q=a_{m+1}^{p_{m+1}}*a_{m+2}^{m+2}...*a_k^{p_k}
那么
varphi left( nright) =nprod ^{k}_{i=1}left( 1-dfrac {1}{p_{i}}right)
varphi left( aright) =aprod ^{m}_{i=1}left( 1-dfrac {1}{p_{i}}right)
varphi left( bright) =bprod ^{k}_{i=m+1}left( 1-dfrac {1}{p_{i}}right)
因为n=a*b
显然
varphi left( nright) =varphi left( aright) varphi left( bright)
这种方法也是常见的证明一个函数是积性函数的方法
2.sum_{d|n}phi(d)=n
3.1到n中与n互质的数的和为n*dfrac{phi(n)}{2}(n>1)
计算方法
sqrt(n)计算单值欧拉函数
假设我们需要计算phi(n)
分情况讨论
1.当n=1时
很明显,答案为1
2.当n为质数时
根据素数的定义,答案为n-1
(仅有n与n不互质)
3.当$n$为合数时
我们已经知道了n为素数的情况
不妨对n进行质因数分解
设n=a_1^{p_1}*a_2^{p_2}...*a_k^{p_k}
假设$k=1$
那么phi(p^k)=p^k-p^{k-1}
证明:
考虑容斥,与一个数互素的数的个数就是这个数减去与它不互素的数的个数
因为p是素数,所以在p^k中与其不互素的数为1*p,2*p....p^{k-1}*p,有p^{k-1}个
得证
当kneq 1时
phi(n)
=varphi left( a^{p_{1}}_{1}a^{p_{2}ldots }_{2}a^{Pk}_{k}right)
=prod ^{k}_{i=1}a^{P_i}-a^{P_{i}-1}_{i}
=prod ^{k}_{i=1}a^{Pi}_{i}(1-dfrac {1}{p_{i}})
=n*prod ^{k}_{i=1}(1-dfrac {1}{p_{i}})
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#define LL long long
using namespace std;
int main()
{
LL N;
while(cin>>N&&N!=0)
{
int limit=sqrt(N),ans=N;
for(int i = 2; i <= limit ; ++i)
{
if(N%i==0) ans=ans/i*(i-1);
while(N%i==0) N=N/i;
}
if(N>1) ans=ans/N*(N-1);
printf("%dn",ans);
}
return 0;
}
线性筛
因为欧拉函数是积性函数
因此可以使用线性筛法
性质1
若p为素数,则varphi left( pright) =p-1
证明:
在1-p中,只有(p,p)neq1
性质2
若i mod p neq 0,且p为素数
则varphi left( i*pright) =varphi left( iright) *varphi left( pright)
=varphi left( iast pright) =varphi left( iright) ast left( p-1right)
这一步同时利用了性质1和欧拉函数的积性
性质3
若i mod p = 0,且p为素数,
则varphi left( iast pright) =varphi left( iright) ast p
证明:
没怎么看懂,丢一个链接
http://blog.csdn.net/Lytning/article/details/24432651
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#define LL long long
using namespace std;
const int MAXN=1e6+10;
int prime[MAXN],tot=0,vis[MAXN],phi[MAXN],N=10000;
void GetPhi()
{
for(int i=2;i<=N;i++)
{
if(!vis[i])
{
prime[++tot]=i;
phi[i]=i-1;
}
for(int j=1;j<=tot&&prime[j]*i<=N;j++)
{
vis[ i*prime[j] ] = 1;
if(i%prime[j]==0)
{
phi[ i*prime[j] ]=phi[i]*prime[j];
break;
}
else phi[ i*prime[j] ]=phi[i]*(prime[j]-1);
}
}
}
int main()
{
GetPhi();
cin>>N;
printf("%dn",phi[N]);
return 0;
}
例题
放几道水题
http://poj.org/problem?id=2407
http://poj.org/problem?id=2478
https://www.luogu.org/problemnew/show/P2158
- 这个恶意软件“奇葩”的反虚拟机技巧
- Android漏洞CVE-2015-3825分析及exploit实战:从Crash到劫持PC
- VaultPasswordView:可用于查看windows Vault密码的工具
- 逆向工厂(二):静态分析技术
- 打开文件夹就运行?COM劫持利用新姿势
- Java集合总览
- 常见面试题之ListView的复用及如何优化
- 自定义圆形控件RoundImageView并认识一下attr.xml
- 自定义带图片和文字的ImageTextButton
- 超值干货:个人开发者如何使用免费又简单的开发后台
- 【周末分享】解决中文排版错位的JustifiedTextview控件
- 超级网络
- c++ fstream + string 处理大数据
- 超炫的FlowingDrawer效果
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法