zoukankan      html  css  js  c++  java
  • 数论小结

    一. 素数筛、素数表

    1.小区间素数(1e6、1e7):

    bool notprime[MAXN+10]; //判断i是否为素数
    int prime[MAXN+10];     //存放素数
    void getPrime()
    {
        memset(notprime, false, sizeof(notprime));
        notprime[0] = notprime[1] = true;
        prime[0] = 0;   //存放素数个数
        for (int i = 2; i<=MAXN; i++)
        {
            if (!notprime[i])prime[++prime[0]] = i;
            for (int j = 1; j<=prime[0]&& prime[j]<=MAXN/i; j++)
            {
                notprime[prime[j]*i] = true;
                if (i%prime[j] == 0) break;
                /*
                    当i为合数且能被prime[j]整除时,i*prime[j+1] = k*prime[j]*prime[j+1] = 
                    k*prime[j+1]*prime[j] = i'*prime[j],可知肯定能够在后面被prime[j]乘以
                    一个更大的数i'筛掉。因此,当prime[j]能整除i时,就应该退出循环,保证每
                    个合数只被它的最小素因子筛掉。
                */
            }
        }
    }

    2.大区间素数筛(1e12):

    int prime[MAXN+10];
    bool notprime[MAXN+10];
    void getPrime()
    {
        memset(notprime, false, sizeof(notprime));
        notprime[0] = notprime[1] = true;
        for(int i = 2; i<=MAXN; i++)
        {
            if(!notprime[i]) prime[++prime[0]]=i;
            for(int j = 1; j<=prime[0]&&prime[j]<=MAXN/i; j++)
            {
                notprime[prime[j]*i] = 1;
                if(i%prime[j]==0) break;
            }
        }
    }
    
    void getPrime2(int L, int R)
    {
        memset(notprime, false, sizeof(notprime));
        for(int i = 1; i<=prime[0]&& prime[i]<=R/prime[i]; i++)
            for(int j = max(2,(int)ceil(1.0*L/prime[i])); j<=R/prime[i]; j++)
                notprime[j*prime[i]-L+1] = true;
    }

    3.题目:

    LightOJ1259 Goldbach`s Conjecture(素数表)
    LightOJ1197 Help Hanzo(大区间素数筛)

    二.唯一分解定理

    1.模板:

    bool notprime[MAXN];
    int prime[MAXN/10];
    void getPrime()
    {
        memset(notprime, false, sizeof(notprime));
        notprime[0] = notprime[1] = true;
        prime[0] = 0;
        for (int i = 2; i<MAXN; i++)
        {
            if (!notprime[i])prime[++prime[0]] = i;
            for (int j = 1; j<=prime[0]&& prime[j]<MAXN/i; j++)
            {
                notprime[prime[j]*i] = true;
                if (i%prime[j] == 0) break;
            }
        }
    }
    
    int fatCnt;
    LL factor[1000][2];
    int getFactors(LL n)
    {
        LL tmp = n;
        fatCnt = 0;
        for(int i = 1; prime[i]<=tmp/prime[i]; i++)
        {
            if(tmp%prime[i]==0)
            {
                factor[++fatCnt][0] = prime[i];
                factor[fatCnt][1] = 0;
                while(tmp%prime[i]==0) tmp /= prime[i], factor[fatCnt][1]++;
            }
        }
        if(tmp>1) factor[++fatCnt][0] = tmp, factor[fatCnt][1] = 1;
    }

    2.题目:

    poj2773
    poj3904 Sky Code
    UVA1635 Irrelevant Elements
    LightOJ1341 Aladdin and the Flying Carpet
    LightOJ1336 Sigma Function 
    LightOJ1236
    LightOJ1138
    LightOJ1220 

    三. 欧几里得、扩展欧几里得

    1.欧几里得算法:

    LL gcd(LL a, LL b)
    {
        return b==0?a:gcd(b,a%b);
    }

    辗转相除法证明:

    设 d = gcd(a,b),

    那么 d | a 、d | b  …… 符号“|”表示整除

    可知a可表示为:a = k*b + r,移项得:r = a - k*b,两边模d,

    那么:r%d = a%d - k*b%d = 0,

    所以 d | r ,所以 gcd(b,r)= gcd(a,b)。

    2.扩展欧几里得:

    LL exgcd(LL a, LL b, LL &x, LL &y)
    {
        if(a==0 &&b==0) return -1;
        if(b==0) {x=1; y=0; return a;}
        LL d = exgcd(b,a%b,y,x);
        y -= a/b*x;
        return d;
    }

    2.1.算法证明:

    设如下两个方程:

    ax+by = gcd(a,b) ;

    bx’+(a%b)y’ = gcd(b,a%b);

    又因为:gcd(a,b) = gcd(b,a %b),

    那么ax+by = bx’+(a%b)y’ = bx’ +(a – a/b*b)*y’ = ay’ + b(x’ – a/b*y’),

    由恒等关系有: x = y’ , y = (x’ – a/b*y’)

    2.2.1.求 a*x + b*y = gcd(a,b) = d 的一组解,其中要求a>0、b>0。

    假设求得一组解为 (x0,y0),那么通解为:(x0+k*b/ d,y0-k*a/ d),k为整数。

    2.2.2.求 a*x + b*y = c 的一组解,其中要求a>0、b>0。

    先求出 gcd(a,b),如果 gcd(a,b)不能整除c,则无解。如果能整除:

    求出a*x + b*y = gcd(a,b)= d 的一组解(x0,y0),那么通解为 (x0*c/d+k*b/d,y0*c/d-k*a/d),k为整数。

    3.题目:

    POJ1061 青蛙的约会
    POJ2115 C Looooops
    HackerRank leonardo-and-lucky-numbers
    POJ The Balance

    四.欧拉函数

    1. 公式:

    euler(n)= n*[ (1-1/p1)*(1-1/p2)……*(1-1/pk) ],p为n的质因子。公式根据容斥原理(展开后可知),中括号内的为百分比。

    2.筛法欧拉函数:

    int euler[MAXN];
    void getEuler()
    {
        memset(euler, 0, sizeof(euler));
        euler[1] = 1;
        for(int i = 2; i<MAXN; i++) if(!euler[i]) {
            for(int j = i; j<MAXN; j += i)
            {
                if(!euler[j]) euler[j] = j;
                euler[j] = euler[j]/i*(i-1);
            }
        }
    }

    3.题目:

    POJ2478 Farey Sequence
    UVA11426 GCD - Extreme (II) 
  • 相关阅读:
    基本数据类型与其包装类型
    String与常量池(JDK1.8)
    数据库知识归纳(面试向)
    HashMap、ConcurrentHashMap以及HashTable(面试向)
    Java多线程基础(面试向)
    Java的类加载
    Sql语句的一些事(二)
    RUBY惯用方法(转)
    Ruby中区分运行来源的方法(转)
    ruby安装devkit
  • 原文地址:https://www.cnblogs.com/DOLFAMINGO/p/8409471.html
Copyright © 2011-2022 走看看