zoukankan      html  css  js  c++  java
  • 欧拉函数 &【POJ 2478】欧拉筛法

    通式: $phi(x)=x(1-frac{1}{p_1})(1-frac{1}{p_2})(1-frac{1}{p_3}) cdots (1-frac{1}{p_n})$

    若n是质数p的k次幂:$phi(n)=p^k-p^{k-1}=(p-1)p^{k-1}$,因为除了p的倍数外,其他数都跟n互质。

    设n为正整数,以$phi(n)$表示不超过n且与n互素的正整数的个数,称为n的欧拉函数值,这里函数φ:N→N,n→φ(n)称为欧拉函数。
    欧拉函数是积性函数——若m,n互质, $phi(mn)=phi(m)phi(n)$
    特殊性质:当n为奇数时,  $phi(2n)=phi(n)$, 证明与上述类似。
    若n为质数则 $phi(n)=n-1$

    zky学长上课时留的思考题,关于$n = sum_{d|n} phi(d)$的证明:

    ①当$n$为质数时,显而易见$n= sum_{d|n} phi(d)= phi(1) + phi(n) = n$

    ②当$n=p^a$时

    [ egin{aligned} n & = sum_{d|n} phi(d) \ & = sum_{i=0}^a phi(p^i) \ & = phi(1) + phi(p^1) + phi(p^2) + cdots + phi(p^a) \ & = 1 + p^1-p^0+p^2-p^1+ cdots +p^a-p^{a-1} \ = p^a = n end{aligned} ]

    ③当$n$为其他情况时,将$n$分解质因数得$n=p_{1}^{a_{1}}p_{2}^{a_{2}} cdots p_{k}^{a_{k}}$,对于每个$p_{i}^{a_{i}}$是互质的,那么由积性函数的性质($n$和$m$互质,则$phi(nm)=phi(n)phi(m)$)和②中的证明可以得出结论,是不是很简单啊

    单个欧拉函数求法:

    int euler_phi(int n){
    	int m=(int)sqrt(n+0.5);
    	int ans=n;
    	for(int i=2;i<=m;++i)
    		if (n%i==0){
    			ans=ans/i*(i-1);
    			while (n%i==0)
    				n/=i;
    		}
    	if (n>1) ans=ans/n*(n-1);
    }
    

    欧拉筛,参考白书上的:

    int phi[maxn];
    void phi_table(int n){
    	for(int i=2;i<=n;++i)
    		phi[i]=0;
    	phi[1]=1;
    	for(int i=2;i<=n;++i)
    		if (!phi[i])
    			for(int j=i;j<=n;j+=i){
    				if (!phi[j])
    					phi[j]=j;
    				phi[j]=phi[j]/i*(i-1);
    			}
    }
    

    POJ 2478 O(n)内筛法:

    #include<cstdio>
    using namespace std;
    const int N=1000003;
    int num=0,prime[N],phi[N];
    bool notp[N];
    inline void shai(){
    	phi[1]=1;
    	for(int i=2;i<N;++i){
    		if (!notp[i]){
    			prime[++num]=i;
    			phi[i]=i-1;
    		}
    		for(int j=1;j<=num&&i*prime[j]<N;++j){
    			notp[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]*phi[prime[j]];
    		}
    	}
    }
    int main(){
    	shai();
    	int x;
    	long long ans;
    	scanf("%d
    ",&x);
    	while (x){
    		ans=0;
    		for(int i=2;i<=x;++i)
    			ans+=phi[i];
    		printf("%I64d
    ",ans);
    		scanf("%d
    ",&x);
    	}
    	return 0;
    }
    

    这样就可以啦

  • 相关阅读:
    MessageDigest简介
    深入入门正则表达式(java)
    JAVA 正则 Pattern 和 Matcher
    理解Servlet过滤器 (javax.servlet.Filter)
    Java 之 I/O 系列 01 ——基础
    finally块中的代码一定会执行吗?
    wait(), notify(),sleep详解
    Java 多线程——基础知识
    集合迭代时对集合进行修改抛ConcurrentModificationException 原因 以及解决方案
    深入理解ServletRequest与ServletResponse
  • 原文地址:https://www.cnblogs.com/abclzr/p/5298051.html
Copyright © 2011-2022 走看看