• BDFZOI 数论小结1(筛法、欧拉phi函数)


    Eratothenes筛法

    描述

    找出N以内的素数,并求和。

    输入一个正整数N,N<=10^7输出一个整数,表示N以内素数之和。

    样例输入

    10

    样例输出

    17

    提示

    1.结果可能很大
    2.Eratosthenes筛法的复杂度为O(NlglgN),能在1s内找出10^7以内的素数

    代码:

     1 #include<iostream>
     2 using namespace std;
     3 int a[10000005];
     4 int n;
     5 int main(){
     6     cin>>n;
     7     int i, j;
     8     for(i = 2; i <= n/2; i++){
     9         if(a[i]==0)
    10         for(j = i; j <= n/i; j++){
    11             a[i*j] = -1;
    12         }
    13     }
    14     long long ans = 0;
    15     for(i = 2; i <= n; i++){
    16         if(a[i]!=-1) 
    17             ans+=i;
    18     }
    19     cout<<ans<<endl;
    20     return 0;
    21 } 

    备注:

    筛法的思想很简单。从2开始,把2的所有倍数标记为-1,再找到下一个未被标记的数(质数),继续划掉它的倍数。注意j从i开始循环就好了,因为更小的倍数已经在之前删更小的质数倍数的时候删过了。

    答案用long long存。。


    欧拉Phi函数

    描述

    在数论中,对于正整数n,函数phi(n)的值是"小于等于n的数中,与n互质的数的个数”。

    也可以用下面公式计算:phi(n)=n×(1-1/p1)×(1-1/p2)...×(1-1/pm),其中p1,p2...pm为n的所有质因数(即又是质数又是n的因数)。

    输入一个正整数n,n<=10^7输出一个整数,既phi(n)的值

    样例输入

    45

    样例输出

    24

    提示

    45有质因数3和5,那么phi(45)=45(1-1/3)(1-1/5)=24
    n本身也是自己的因数,但不一定是质数

    代码:

     1 #include<iostream>
     2 #include<cmath>
     3 #include<cstdlib>
     4 using namespace std;
     5 int num;
     6 int a[10000005];
     7 int phi(int n){
     8     int ans = n;
     9     int m = (int)sqrt(n+0.5);
    10     int i;
    11     for(i = 2; i <= m; i++){
    12         if(n%i == 0){
    13             ans = ans/i*(i-1);
    14             while(n%i == 0) n/=i;
    15         }
    16     }
    17     if(n > 1)ans = ans/n*(n-1);
    18     return ans;
    19 }
    20 int main(){
    21     cin>>num;
    22     int ans = phi(num);
    23     cout<<ans<<endl;
    24     return 0;
    25 } 

    备注:

    参考《入门经典》。其实也是运用了筛法的思想。最开始我用先生成素数表再逐个判断虽然慢点也AC了。实际上,从2开始,每找到一个素因子就把它除干净,这样保证找到的每一个因子都是素数。注意:i循环到√n就可以了,因为最多只会有一个大于√n的素因子(两个的话乘起来不就超了么),最后加一个if(n>1)把最后那个最大的素因子算上就好了。


    欧拉Phi函数升级版

    描述

    在数论中,对正整数n,phi(n)的值是"小于等于n的数中,与n互质的数的个数”,并且也是模n乘法群Zn*的规模。

    可以用下面公式计算:phi(n)=n(1-1/p1)(1-1/p2)...(1-1/pm),其中p1,p2...pm为n的所有质因数。

    输入一个正整数n,n<=10^5输出一个整数,phi(1)+phi(2)+...+phi(n)的值

    样例输入

    20

    样例输出

    128

    提示

    1.结果可能很大
    2.O(NlogN)才能过,借鉴Eratosthenes筛法

    代码:

     1 #include<iostream>
     2 #include<cstring>
     3 using namespace std;
     4 int phi[100005];
     5 void phi_table(int n){
     6     memset(phi, 0, sizeof(phi));
     7     phi[1] = 1;
     8     for(int i = 2; i <= n; i++)
     9         if(!phi[i])
    10             for(int j = i; j <= n; j+=i){
    11                 if(!phi[j]) phi[j]=j;
    12                 phi[j] = phi[j]/i*(i-1);
    13             }
    14 }
    15 int main(){
    16     int num;
    17     cin>>num;
    18     phi_table(num);
    19     long long ans = 0;
    20     int i;
    21     for(i = 1; i <= num; i++)
    22         ans+=phi[i];
    23     cout<<ans;
    24     return 0;
    25 } 

    备注:

    参考《入门经典》。

    升级版就是求1~n所有phi(x)之和。phi(1)=1..

    从2开始循环,如果phi[i]==0的话说明这个数是质数。然后开始筛,对于所有i的倍数,如果还为0,就让它等于本身。然后把phi[j]乘上这个1-1/该素因子。相当于每处理一个数就把1~n内所有以它为素因子的数都处理了。

    这样就实现了NlogN的复杂度??

  • 相关阅读:
    JAVA NIO之文件通道
    Java NIO之缓冲区
    LinkedList 源码分析(JDK 1.8)
    ArrayList 源码详细分析
    自己动手实现一个简单的JSON解析器
    科普:String hashCode 方法为什么选择数字31作为乘子
    LinkedHashMap 源码详细分析(JDK1.8)
    HashMap 源码详细分析(JDK1.8)
    python创建目录
    python3 内置方法 字符串转换为字典
  • 原文地址:https://www.cnblogs.com/fangziyuan/p/6622733.html
Copyright © 2020-2023  润新知