初级数论(未完待续……)

一、模运算性质

  1. ( a + b ) % m = ( ( a % m ) + ( b % m ) ) % m;
  2. ( a - b ) % m = ( ( a % m ) - ( b % m ) ) % m;
  3. ( a * b ) % m = ( ( a % m ) * ( b % m ) ) % m;

二、快速幂

1、普通快速幂

核心思想:a^n = a^(x1+x2+x3+x4+......+xn) = a^x1 * a^x2 * a^x3 * ...... *  a^xn;

快速的理解就是:x1,x2,x3,x4是倍数的增长,能达到少循环的效果。

引入二进制能更好判断什么时候乘a的幂;

例如:a^11=a^(1+2+8),他是如何出来的呢???11的二进制1011==1*(2^3)+0*(2^2)+(1*2^1)+(1*2^0);这样就可以进行加乘了。

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;

LL fastPow(LL a,LL n)
{
    LL base=a;         //作用是a的多少次幂
    LL res=1;
    while(n)
    {
        if(n&1)        //判断是否要乘
            res*=base;
        base*=base;    //更新n的数
        n>>=1;        //右移
    }
    return res;
}

int main()
{
    ios::sync_with_stdio(false);
    LL a,b,c;
    while(cin>> a >> b)
    {
        LL ans;
        ans=fastPow(a,b);
        cout << ans << endl;
    }
    return 0;
}

2、快速幂取模

    利用上面的性质( a * b ) % m = ( ( a % m ) * ( b % m ) ) % m;

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;

LL fastPow(LL a,LL n,LL c)
{
    LL base=a;
    LL res=1;
    const LL mod=c;
    while(n)
    {
        if(n&1)
            res=(res*base)%mod;
        base=(base*base)%mod;
        n>>=1;
    }
    return res;
}

int main()
{
    ios::sync_with_stdio(false);
    LL a,b,c;
    while(cin>> a >> b >> c)
    {
        LL ans;
        ans=fastPow(a,b,c);
        cout << ans << endl;
    }
    return 0;
}

三、ged&&lcm

1、gcd模板

typedef long long LL;
LL gcd(LL a,LL b)
{
    return b?gcd(b,a%b):a;
}

上述的是运用了gcd(a,b)=gcd(b,a%b)的性质;    

c++中封装了gcd,可以直接调用:__gcd(a,b);

2、lcm

lcm(a,b)=a*b/gcd(a,b);

3、gcd与lcm的常用性质

  1. a,b可以分解成素数的因子;
  2. gcd(a,b)中只包含了所有a,b的全部公共素因子(取交集)(可以想象把a,b分解成因子,公共的必定能整除a,b);
  3. lcm(a,b)中包含了a,b所有的素因子(取并集);
  4. lcm*gcd=a*b;
  5. lcm/gcd=(a/gcd)*(b/gcd);
  6. gcd(k*a,k*b)=k*gcd(a,b);
  7. lcm(k*a,k*b)=k*lcm(a,b);

四、埃式素数筛

const int MAXN=1e7;         //定义你所需要的空间大小
int prime[MAXN+1];          //存放素数
bool visit[MAXN+1];         //筛板

int E_sieve(int n)          //埃式筛法
{
    for(int i=0;i<=n;i++)   //将筛板初始化
        visit[i]=0;
    for(int i=2;i*i<=n;i++) //遍历。此处是经过优化的i*i<=n比i<=sqrt(n)更快
    {                       //such as:非素数k一定能被sqrt(k)整除;
        if(visit[i]==0)     //开始筛i的倍数
        {
            for(int j=i*i;j<=n;j+=i)
                visit[j]=1
        }
    }
    int k=0;                //统计素数的个数
    for(int i=2;i<=n;i++)   //存放素数放到prime中
    {
        if(visit[i]==0)
            prime[++k]=i;
    }
    return k;
}
发布了11 篇原创文章 · 获赞 18 · 访问量 1944

猜你喜欢

转载自blog.csdn.net/acm_durante/article/details/103795434