欧拉函数与欧拉函数的递推总结+例题POJ2478
来源:互联网 发布:演技 知乎 编辑:程序博客网 时间:2024/05/22 00:36
先来介绍几个与欧拉函数有关的定理:
定理一:设m与n是互素的正整数,那么
定理二:当n为奇数时,有。
因为2n是偶数,偶数与偶数一定不互素,所以只考虑2n与小于它的奇数互素的情况,则恰好就等于n的欧拉函数值。
定理三:设p是素数,a是一个正整数,那么
关于这个定理的证明用到容斥:
由于表示小于与互素数的正整数个数,所以用减去与它不互素的数的个数就行了。
那么小于与不互素数的个数就是p的倍数个数,有个。所以定理得证。
定理四:设为正整数n的素数幂分解,那么
这个定理可以根据定理一和定理三证明,其实用到的就是容斥。如果对容斥熟悉,其实完全就可以直接容斥。
定理五:设n是一个正整数,那么
这个其实可以看莫比乌斯反演就明白了。
定理六:设m是正整数,(a,m)=1,则:是同于方程的解。
定理七:如果n大于2,那么n的欧拉函数值是偶数。
1.求单个数的欧拉函数(白书版本)
int euler_phi(int n){ int ans=n; for(int i=2;i*i<=n;i++) if(n%i==0) { ans=ans/i*(i-1); while(n%i==0) n/=i; } if(n>1) ans=ans/n*(n-1); return ans; }}
2.1求1~n中所有数的欧拉phi函数值(这里就不引用白书上的了,太慢了。。。)
void Solve(void){ for(int i=1; i<n; i++) p[i] = i; for(int i=2; i<n; i+=2) p[i] >>= 1; for(int i=3; i<n; i+=2) { if(p[i] == i) { for(int j=i; j<n; j+=i) p[j] = p[j] - p[j] / i; } }}
算法原理:开始令i的欧拉函数值等于它本身,如果i为偶数,可以利用定理二变为求奇数的。若p是一个正整数满足,那么p是素数,在遍历过程中如果遇到欧拉函数值等于自身的情况,那么说明该数为素数。把这个数的欧拉函数值改变,同时也把能被该素因子整除的数改变。
2.2 求1~n中欧拉函数的改进版(主要看n大不大)
先打个素数表:
bool isprime[n];long long num_prime;void get_prime(){ memset(isprime,true,sizeof(isprime)); isprime[0]=isprime[1]=false; for(int i=2;i*i<n;i++){ if(isprime[i]){ num_prime++; for(int j=i*i;j<=n;j+=i) isprime[i]=false; } }}然后根据递推:
对于任意一个能被n整除的质数,有m = n/p
当m%p == 0 的时候,phi(n) = phi(m)*p
当m%p != 0的时候,phi(n) = phi(m)*(p-1)
long long dp[n]= {0ll};void Solve(void){ get_prime(); for(int i=2; i<n; ++i) { if(is_prime[i]) dp[i]=i-1; else { for(int j=0; j<num_prime; ++j) if(i%prime[j]==0) { if((i/prime[j])%prime[j]==0) dp[i]=dp[i/prime[j]]*prime[j]; else dp[i]=dp[i/prime[j]]*(prime[j]-1); break; } } }}
递推式证明:
1)由质因数分解定理得,在n中至少能够分解出一个素数p,导致 n = p*m,那么可以将1~n划分为一个区间的集合{ [m*(i-1) , m*i ] , 1<=i<=p },则对于每个区间[m*(i-1)+1,m*i],其中的每个数可以看做m*(i-1)+j (1<=j<=m)。
2)所以gcd ( m*(i-1)+j , m )
= gcd ( m , (m*(i-1)+j)%m ) (根据秦九韶辗转相除法)
=gcd ( m , j )
那么也就是每个区间对应位置的数均与1~m中的某个数gcd相同,互质便是gcd(a,b)==1,所以1~n中与m互质的数有p*phi(m)个。
3)那么我们接下来进行分类讨论:
若m%p == 0 , 那么 m = a*p(a为一个正整数),所以若gcd(b,m) == 1 ,那么 gcd ( b , p ) == 1 , 所以 gcd ( m*p , b ) == 1 , 即gcd ( n , b ) == 1 ,所以在这种情况与m互质的数均与n互质,所以phi(n) = phi(m)*p;
若m%p != 0 , 那么若gcd ( b , m) == 1 , gcd ( b , p ) == p , 那么 gcd ( n , b ) == p,所以1~m与m互质的数为q,若m%p != 0 , 那么与m互质且与p不互质的数是q*p,因此在n当中这样的数有phi(m)个,所以 phi(n) = phi(m)*p - phi(m)
例题:POJ 2478
->题目传送门<-
题意:输入n,求n以内的数的欧拉函数的和(分子分母互素)2.1版:422MS
#include <stdio.h>#include <iostream>#include <cstring>using namespace std;const int MAX=1000010;int prime[MAX]={0},num_prime=0;//num_pirme记录素数个数bool is_prime[MAX];void GetPrime(){ memset(is_prime,true,sizeof(is_prime)); is_prime[0]=is_prime[1]=false; for(int i=2;i*i<MAX;i++) { if(is_prime[i]) for(int j=i*i;j<=MAX;j+=i) { is_prime[j]=false; } }}long long p[MAX];void Solve(){ for(int i=1; i<MAX; i++) p[i] = i; for(int i=2; i<MAX; i+=2) p[i] >>= 1; for(int i=3; i<MAX; i+=2) { if(p[i] == i) { for(int j=i; j<MAX; j+=i) p[j] = p[j] - p[j] / i; } }}int main(void){ int n,ncase=1; Solve(); while(scanf("%d",&n)==1 && n) { long long sum=0; for(int i=2;i<=n;i++){ sum+=p[i]; } cout<<sum<<endl; } return 0;}
2.2版:157MS
#include <cstdio>#include <iostream>#include <cstring>using namespace stdconst int maxn=1000010;int prime[maxn],num_prime=0;//num_pirme记录素数个数bool is_prime[maxn];void get_Prime(){ memset(is_prime,true,sizeof(is_prime)); is_prime[0]=is_prime[1]=false; for(int i=2;i*i<maxn;i++) { if(is_prime[i]) prime[num_prime++]=i; for(int j=i*i;j<=maxn;j+=i) { is_prime[j]=false; } }}long long dp[maxn]={0ll};void solve(){ get_Prime(); for(int i=2;i<maxn;++i) { if(is_prime[i]) dp[i]=i-1; else { for(int j=0;j<num_prime;++j) if(i%prime[j]==0) { if((i/prime[j])%prime[j]==0) dp[i]=dp[i/prime[j]]*prime[j]; else dp[i]=dp[i/prime[j]]*(prime[j]-1); break; } } } for(int i=3;i<maxn;++i) dp[i]+=dp[i-1];}int main(void){ int n; solve(); while(scanf("%d",&n)==1 && n) { printf("%lld\n",dp[n]); } return 0;}
借鉴了两篇别人的文章:
关于欧拉函数的递推方法的证明
欧拉函数与欧拉定理
- 欧拉函数与欧拉函数的递推总结+例题POJ2478
- poj2478(欧拉函数)
- poj2478 欧拉函数
- poj2478【欧拉函数】
- POJ2478 && Sicily1089(欧拉函数)
- poj2478 (欧拉函数)
- POJ2478(典型的欧拉函数)
- poj2478 Farey Sequence(线性筛法+欧拉函数+递推)
- POJ2478 Farey Sequence 欧拉函数与素数 数论题
- POJ2478 Farey Sequence,欧拉函数
- poj2478 Farey Sequence (欧拉函数)
- POJ2478 Farey Sequence(欧拉函数)
- POJ2478 Farey Sequence 数论,欧拉函数
- poj2478 Farey Sequence (欧拉函数)
- poj2478 Farey Sequence 欧拉函数的应用
- poj2478 Farey Sequence 欧拉函数性质的简单应用
- 欧拉函数的递推形式
- poj2478解题报告——欧拉函数,筛法
- 调整SortingOrder解决UGUI中粒子层级问题
- easyui-combobox选中下拉框无法显示值
- 《驾驭大数据》 Bill Franks
- QML文档定义对象
- C语言操作大于2G的文件
- 欧拉函数与欧拉函数的递推总结+例题POJ2478
- Linux 基础入门
- sql 盲注之正则表达式攻击
- vector二维数组使用
- python数据持久存储:pickle模块的基本使用
- Python多线程
- 第一张数字货币银行卡问世:线上线下直接刷卡消费,手续费全免,还能贷款
- imgs
- 在hta中使用select下拉框