zoukankan      html  css  js  c++  java
  • 欧拉函数 & 【POJ】2478 Farey Sequence & 【HDU】2824 The Euler function

    http://poj.org/problem?id=2478

    http://acm.hdu.edu.cn/showproblem.php?pid=2824

    欧拉函数模板裸题,有两种方法求出所有的欧拉函数,一是筛法,而是白书上的筛法。

    首先看欧拉函数的性质:

    1. 欧拉函数是求小于n且和n互质(包括1)的正整数的个数。记为φ(n)。
    2. 欧拉定理:若a与n互质,那么有a^φ(n) ≡ 1(mod n),经常用于求乘法逆元。
    3. 若p是一个质数,那么φ(p) = p-1,注意φ(1) = 1。
    4. 欧拉函数是积性函数:(wikipedia:http://zh.wikipedia.org/wiki/%E7%A9%8D%E6%80%A7%E5%87%BD%E6%95%B8
      1. 若m与n互质,那么φ(nm) = φ(n) * φ(m)。
      2. 若n = p^k且p为质数,那么φ(n) = p^k - p^(k-1) = p^(k-1) * (p-1)。(证明还用说么。。。一共p^k能被p整除的就有p^(k-1)个。。所以总数减去即可。。
    5. 当n为奇数时,有φ(2*n) = φ(n)。
    6. $sum_{d|n} varphi (d) = n$,这个性质很重要!

    基于素数筛的求欧拉函数的重要依据:

    设a是n的质因数

    若(n%a == 0 && (n/a)%a == 0) 则 φ(n) = φ(n/a)*a; (性质4的1和2推出,将n变成p1^a1*p2^a2...的形式,那么当前是a,即a^ax,那么根据φ(nm) = φ(n) * φ(m)先拆成m=a^ax,即φ(m)=a^(x-1)*(a-1),这样就是当a|m时乘上a-1,否则乘上a

    若(n%a == 0 && (n/a)%a != 0) 则 φ(n) = φ(n/a)*φ(a)。(性质4的1推出)

    素数筛:

    poj 2478:

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    using namespace std;
    #define rep(i, n) for(int i=0; i<(n); ++i)
    #define for1(i,a,n) for(int i=(a);i<=(n);++i)
    #define for2(i,a,n) for(int i=(a);i<(n);++i)
    #define for3(i,a,n) for(int i=(a);i>=(n);--i)
    #define for4(i,a,n) for(int i=(a);i>(n);--i)
    #define CC(i,a) memset(i,a,sizeof(i))
    #define read(a) a=getint()
    #define print(a) printf("%d", a)
    #define dbg(x) cout << (#x) << " = " << (x) << endl
    #define printarr2(a, b, c) for1(_, 1, b) { for1(__, 1, c) cout << a[_][__]; cout << endl; }
    #define printarr1(a, b) for1(_, 1, b) cout << a[_] << '	'; cout << endl
    inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
    inline const int max(const int &a, const int &b) { return a>b?a:b; }
    inline const int min(const int &a, const int &b) { return a<b?a:b; }
    
    const int N=1000005;
    bool isnotprime[N];
    int prime[N], phi[N], cnt;
    void init() {
    	phi[1]=1;
    	for1(i, 2, N-1) {
    		if(!isnotprime[i]) prime[++cnt]=i, phi[i]=i-1;
    		for(int j=1; j<=cnt && i*prime[j]<N; ++j) {
    			isnotprime[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() {
    	init(); int n;
    	while(n=getint(), n) {
    		long long ans=0;
    		for1(i, 2, n) ans+=phi[i];
    		printf("%lld
    ", ans);
    	}
    	return 0;
    }
    

    hdu 2824:g++是I64d我也是醉了。。。

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    using namespace std;
    #define rep(i, n) for(int i=0; i<(n); ++i)
    #define for1(i,a,n) for(int i=(a);i<=(n);++i)
    #define for2(i,a,n) for(int i=(a);i<(n);++i)
    #define for3(i,a,n) for(int i=(a);i>=(n);--i)
    #define for4(i,a,n) for(int i=(a);i>(n);--i)
    #define CC(i,a) memset(i,a,sizeof(i))
    #define read(a) a=getint()
    #define print(a) printf("%d", a)
    #define dbg(x) cout << (#x) << " = " << (x) << endl
    #define printarr2(a, b, c) for1(_, 1, b) { for1(__, 1, c) cout << a[_][__]; cout << endl; }
    #define printarr1(a, b) for1(_, 1, b) cout << a[_] << '	'; cout << endl
    inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
    inline const int max(const int &a, const int &b) { return a>b?a:b; }
    inline const int min(const int &a, const int &b) { return a<b?a:b; }
    
    const int N=3000015;
    bool isnotprime[N];
    int prime[N], phi[N], cnt;
    void init() {
    	phi[1]=1;
    	for1(i, 2, N-1) {
    		if(!isnotprime[i]) prime[++cnt]=i, phi[i]=i-1;
    		for(int j=1; j<=cnt && i*prime[j]<=N-1; ++j) {
    			int p=prime[j];
    			isnotprime[i*p]=1;
    			if(i%p==0) { phi[i*p]=phi[i]*p; break; }
    			else phi[i*p]=phi[i]*phi[p];
    		}
    	}
    }
    
    int main() {
    	int l, r; init();
    	while(~scanf("%d%d", &l, &r)) {
    		long long ans=0;
    		for1(i, l, r) ans+=phi[i];
    		printf("%I64d
    ", ans);
    	}
    	return 0;
    }
    

    还有一种筛法,不需要求素数。。。有待研究。复杂度比前一种多了两个log,是nloglogn的。。。orz。还是用线性的素数筛吧。。

  • 相关阅读:
    [翻译] JSAnimatedImagesView
    css3 :nth-child 常用用法
    设置屏幕亮度(系统级别和应用级别)
    nodejs 改变全局前缀
    MongoDB数据库和集合的状态信息
    NoSQL架构实践(一)——以NoSQL为辅
    socket.io,系统api,
    svn sc create 命令行创建服务自启动
    background-size background-positon合并的写法
    【转】视频编码与封装方式详解
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/4005096.html
Copyright © 2011-2022 走看看