数学的一些小知识

枚举因子法

bool judge(int n)
{
    if(n==1) return false;
    for(int i=2;i*i<=n;i++)
    {
        if(n%i==0) return false;
        
    }
    return true;
}

 

要把1特判掉。 可以1秒内单次判断1~10^16以内的任意一个素数是否是素数

素数筛:提前处理1~N的全体素数,后可以直接判断是否是素数

const int N=1000001;
bool notprime[N];
void init()
{
    notprime[1]=1;
    for(int i=2;i<N;i++)
    {
        if(notprime[i]==false)
        {
            for(int j=i+1;j<N;j=j+i)
            {
                notprime[j]=true;
            }
        }
    }
}

mertens定理

 

https://wenku.baidu.com/view/c167c17931b765ce05081473.html看一波,嗯,这种东西看不懂还是要看的,不求甚解

可以一秒内10^7以内的质数和合数分离开来,接下来让每个合数只删除一次

欧拉筛(线性筛)每一个素数只被记录一次,每一个合数只会被一个唯一的最小素因子标记一次。

https://wenku.baidu.com/view/4881881daaea998fcc220e99.html    原理还是可以看一下的

大致上讲:每一个数有唯一的最大因子,被唯一筛去,唯一最大因子*小于等于最小质因子就是对应的合数,且筛全了

用了反证。

const int N=1000001;
bool notprime[N];
int prime[N];
int pn;
void init()
{
    pn=0;
    notprime[1]=1;
    for(int i=2;i<N;i++)
    {
        for(notprime[i]==false)
        {
            prime[pn++]=i;
        }
        for(int j=0;j<pn;j++)
        {
            notprime[prime[j]*i]==true;
            if(i%prime[j]==0) break;
        }
    }
}

 

1秒钟处理从10^7~10^8

#include<algorithm>里面有__gcd函数,注意要会用

最大公约数:

设两数为a、b(a>b),用

表示a,b的最大公约数,r=a (mod b) 为a除以b的余数,k为a除以b的商,即

。辗转相除法即是要证明

第一步:令

,则设

第二步:根据前提可知

第三步:根据第二步结果可知,

也是

的因数

第四步:可以断定

互质(这里用反证法进行证明:设

,则

,则

,则a与b的一个公约数

,故c非a与b的最大公约数,与前面结论矛盾,因此c也是b与r的最大公约数)从而可知

,继而

证毕

注:以上步骤的操作是建立在刚开始时

的基础之上的,即m与n亦互质。

百度上的解释,海星,不用想了。

int gcd(int a,int b)
{
    if(b==0) return a;
    return gcd(b,a%b);
}

 

多个数求最大公约数

int gcd(int a,int b)
{
    if(b==0) return a;
    return gcd(b,a%b);
}
int multi_gcd(int a[],int n)
{
    int res=gcd(a[0],a[1]);
    for(int i=2;i<n;i++)
    res=gcd(res,a[i]);
    return res;
}

最小公倍数略。

扩展欧几里得算法:

把这个实现和Gcd的递归实现相比,发现多了下面的x,y赋值过程,这就是扩展欧几里德算法的精髓。

可以这样思考:

对于a'=b,b'=a%b 而言,我们求得 x, y使得 a'x+b'y=Gcd(a',b')

由于b'=a%b=a-a/b*b (注:这里的/是程序设计语言中的除法)

那么可以得到:

a'x+b'y=Gcd(a',b') ===>

bx+(a - a / b * b)y = Gcd(a', b') = Gcd(a, b) ===>

ay +b(x - a / b*y) = Gcd(a, b)

因此对于a和b而言,他们的相对应的p,q分别是 y和(x-a/b*y)

使用扩展欧几里德算法解决不定方程的办法

对于不定整数方程pa+qb=c,若 c mod Gcd(a, b)=0,则该方程存在整数解,否则不存在整数解。

有种较为不严谨的方法证明,不过至少弥补了一点空白,望某些数论大师补充修改:

由于我们知道,存在一组x与y使得a*x+b*y=gcd(a,b)。

将等式两边同时乘以整数k,即a*x*k+b*y*k=gcd(a,b)*k。如果c mod gcd(a,b)=f,则0<=f<gcd(a,b)。

那么可以令c=gcd(a,b)*k+f。这样一来,就有a*x*k+b*y*k+f=c。

若f

0,由于f<gcd(a,b)<=a<=b(假设a<=b),所以不存在f=a*m(m为整数),也就不存在a*(x*k+m)+b*y*k=c。也就是说,不存在a*x+b*y=c的整数解x与y。

所以f=0,即只有当c mod gcd(a,b)=0时,a*x+b*y=c有正整数解。得证。

上面已经列出找一个整数解的方法,在找到p * a+q * b = Gcd(a, b)的一组解p0,q0后,p * a+q * b = Gcd(a, b)的其他整数解满足:

p = p0 + b/Gcd(a, b) * t

q = q0 - a/Gcd(a, b) * t(其中t为任意整数)

至于pa+qb=c的整数解,只需将p * a+q * b = Gcd(a, b)的每个解乘上 c/Gcd(a, b) 即可,但是所得解并不是该方程的所有解,找其所有解的方法如下:

在找到p * a+q * b = Gcd(a, b)的一组解p0,q0后,可以

得到p * a+q * b = c的一组解p1 = p0*(c/Gcd(a,b)),q1 = q0*(c/Gcd(a,b)),p * a+q * b = c的其他整数解满足:

p = p1 + b/Gcd(a, b) * t

q = q1 - a/Gcd(a, b) * t(其中t为任意整数)

p 、q就是p * a+q * b = c的所有整数解。

上面是百度上的https://baike.baidu.com/item/扩展欧几里德算法/1053275?fr=aladdin比较透彻

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

线性同余方程,求逆元

int solve(int a,int b,int n)
{
    int d=gcd(a,n);
    if(b%d==0) return -1;
    int k=b/d;
    int x,y;
    exgcd(a,n,x,y);
    return x*k;
}

分解质因数

算术基本定理https://baike.baidu.com/item/算术基本定理/10920095?fr=aladdin

这个写的通俗易懂,不错。

预处理素数筛

int p[100];
int e[100];
int cnt;
int fenjie(int n)
{
    cnt=0;
    for(int i=0;i<pn&&prime[i]<=n;i++)
    {
        if(n%prime[i]==0)
        {
            p[cnt]=prime[i];
            while(n%prime[i]==0)
            n/=prime[i];
            e[cnt]++;
            cnt++;
        }
        if(n>1) p[cnt]=n;
        e[cnt++]=1;
    }
}

快速幂

long long pow_mod(long long a,long long n,long long m)
{
    long long res=1;
    while(n>0)
    {
        if(n%2==1) res=res*a%m;
        a=a*a%m;
        n/=2;
    }
    return res;
}

费马小定理

模素数是有循环节的,P-1

int getphi(int n)
{
    int ans=n;
    for(int i=2;i*i<=n;i++)
    {
        if(n%i==0) 
        {
            ans-=ans/i;
            while(n%i==0)
            n/=i;
            
        }
    }
    if(n>1) ans-=ans/n;
    return ans;
}

https://baike.baidu.com/item/欧拉函数

baby step giant stephttps://www.cnblogs.com/wondove/p/7976525.html

不行了,看看其他人博客吧

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值