关于数论

\({\color{Red} 声明:由于作者是个蒟蒻,所以本博客只含结论,不含推导过程。如果有大佬想看推导过程可以看 (这里是传送门)}\) oi-wiki,教练HaneDaniko

素数

筛法求素数

  • 用于求1~n的素数

线性筛

点击查看代码
int prime[maxn]; // 保存素数
bool is_not_prime[maxn]={1,1}; // 0和1都不是素数
// 筛选 n 以内的所有素数
void xxs(int n) 
{
    for(int i=2;i<=n;++i) {
        if(!is_not_prime[i]) // 如果i是素数
        { 
            prime[++prime[0]]=i;
        }
        for(int j=1;j<=prime[0]&&i*prime[j]<=n;++j) 
        {
            is_not_prime[i*prime[j]] = 1;
            // 如果i中包含了该质因子,则停止
            if(i%prime[j]==0)break;
        }
    }
}

埃氏筛

点击查看代码
int n,a[50000005];
int main()
{
	scanf("%d", &n);
	for(int i=1;i<=n;i++)a[i]=1;
	for(int i=2;i<=n;i++)
	{
		if(a[i] == 0)continue;
		for(int j=i;j<=n/i;j++)
		{
			a[i*j] = 0;
		}
	}
	for(int i=2;i<=n;i++)
	{
		if(a[i])printf("%d\n",i);
	}
	return 0;
}

欧拉函数

  • 用于求i:1~n中与n互质的数(gcd(i,n)==1)的个数,用\(\varphi\)表示。
  • 特殊性质:
  1. \(\varphi(1)=1\)
  2. p是一个素数\(\varphi(p)=p-1\),\(\varphi(p^k)=(p-1)\times p^{k-1}\)
  3. \(gcd(a,b)=1\),则\(\varphi(a\times b)=\varphi(a)\times \varphi(b)\),特殊的:对于奇数n\(\varphi(2n)=\varphi(n)\)

求欧拉函数

  • 只求一个数的欧拉函数
点击查看代码
int euler_phi(int n) 
{
    int m=int(sqrt(n+0.5));
    int ans=n;
    for(int i=2;i<=m;i++) 
    {
        if (n % i == 0) 
        {
            ans=ans/i*(i-1);
            while (n%i==0)n/=i;
        }
    }
    if(n>1)ans=ans/n*(n-1);
    return ans;
}
  • 求1~n所有数的欧拉函数
点击查看代码
int n,phi[N],prime[N],tot;
bool not_prime[N];
void getPhi() 
{
    int i,j,k;
    phi[1]=1;
    for(i=2;i<=n;++i) 
    {
        if(!not_prime[i]) 
        {
            prime[++tot]=i;
            phi[i]=i-1; 
        }
        for(j=1;j<=tot;++j) 
        {
            k=i*prime[j];
            if(k>n)break;
            not_prime[k]=true;
            if(i%prime[j]==0) 
            { 
                phi[k]=prime[j]*phi[i];
                break;
            } 
            else phi[k]=(prime[j]-1)*phi[i];
        }
    }
}

费马小定理

  • 模数为素数
  • 若p是素数,a不是p的倍数(或\(gcd(a,p)=1\)),则\(a^{p-1} \equiv 1 \pmod p\)
  • 另一种形式:若p为素数,对任意整数a,有\(a^p\equiv a \pmod p\)

欧拉定理

  • 费马小定理是用来阐述在素数模下,指数的同余性质。当模是合数时,就要用范围更广的欧拉定理了。
  • \(gcd(a,m)=1\),则\(a^{\varphi(m)}\equiv 1 \pmod m\)
  • 特别的:当m为素数时,就是费马小定理。

拓展欧拉定理

\[a^b= \begin{cases} a^{b\,mod\,\varphi(p)} \qquad\qquad gcd(a,p)=1\\ a^b \qquad\qquad\qquad\,\;\;\; gcd(a,p)\neq1 ,b<\varphi(p)\pmod m\\ a^{b\,mod\,\varphi(p)+\varphi(p)} \qquad gcd(a,p)\neq1 ,b\ge\varphi(p) \end{cases} \]

最大公约数

  • 新版本的dev中有直接求最大公约数的函数__gcd(a,b)(这是两个下划线),据说比赛里也可以用。

辗转相除法求最大公约数

  • 原理:\(gcd(x,y)=gcd(y,x\;mod\;y)\)
点击查看代码
//递归形式
int gcd(int x,int y) 
{
    return(y==0?x:gcd(y,x%y));
}

//非递归形式
int gcd(int x,int y) 
{
    int r=x%y;
    while(r) 
    {
        x=y;
        y=r;
        r=x%y;
    }
    return y; 
}

裴蜀定理

  • a,b为两个不全为零的整数,对任意整数x,y,满足\(gcd(a,b)\,|\,ax+by\),
    则存在整数x,y使\(ax+by=gcd(a,b)\)
  • 逆定理:a,b是不全为零的整数,若\(d(d>0)\)是a,b的公因数,且存在整数x,y,使得\(ax+by=d\),则\(d=gcd(a,b)\)
  • 特殊的,a,b为不全为零的整数,若存在整数x,y,使得\(ax+by=1\),则a,b互质。

拓展欧几里得

  • 常用于求\(ax+by=gcd(a,b)\)的一组整数解(x,y为未知数)。

求任意一组解

点击查看代码
int exgcd(int a,int b,int &x,int &y) 
{
    if(b==0) 
    {
        x = 1;
        y = 0;
        return a;
    }
    int ret=exgcd(b,a%b,x,y);
    int t=x;
    x=y;
    y=t-a/b*y;
    return ret;
}
  • 这个函数的返回值既不是x也是不y,而是a,b的最大公约数,这也是函数传参数时要带&的原因(这样可以改变原参数值)。

求最小正整数解和同解

  • \((x_0,y_0)\),为任意一组解,则同解\((x,y)\)

\[\begin{cases} x=x_0+b/gcd(a,b)\times t \\y=y_0-a/gcd(a,b)\times t\end{cases} \]

其中t为任意整数

卢卡斯定理(lucas)

  • 用来求大组合数取模的问题,其中模数必须是质数。
  • \(C_n^m\equiv C_{n/p}^{m/p} \times C_{n\,mod\,p}^{m\,mod\,p}\pmod p\)

板子

点击查看代码
#define int long long

const int mod=10007;

int t,n,m;
int a[100000];

int qpow(int a,int k,int p)
{
    int res=1;
    while(k)
    {
        if(k&1)res=res*a%p;
        k>>=1;
        a=a*a%p;
    }
    return res;
}

int niyuan(int a,int p)
{
    return qpow(a,p-2,p);
}

int c(int n,int m,int p)
{
    if(n<m)return 0;
    return jc[n]*niyuan(jc[m]*jc[n-m]%p,p)%p;
}

int lucas(int n,int m,int p)
{
    if(m==0)return 1;
    return (c(n%p,m%p,p)*lucas(n/p,m/p,p))%p;
}

中国剩余定理

  • 中国剩余定理可以求解如下形式的一元线性方程组(其中\(n_1,n_2,\dots,n_k\)两两互质)。

\[x\equiv \begin{cases} a_1\pmod{n_1} \\ a_2\pmod{n_2} \\ \vdots \\a_k\pmod{n_ k}\end{cases}\]

板子

点击查看代码
int exgcd(int a,int b,int &x,int &y)
{
    if(b==0)
    {
        x=1;
        y=0;
        return 0;
    }
    int ret=exgcd(b,a%b,x,y);
    int t=x;
    x=y;
    y=t-a/b*y;
    return ret;
}

int crt(int k,int a[],int r[])
{
    int N=1,ans=0;
    for(int i=1;i<=k;i++)
    {
        N=N*r[i];
    }
    for(int i=1;i<=k;i++)
    {
        int m=N/r[i],x,y;
        exgcd(m,r[i],x,y);
        ans=((ans+a[i]*m*x)%N+N)%N;
    }
    return ans;
}
posted @ 2024-03-25 15:54  藦兲轮の约顁  阅读(31)  评论(6编辑  收藏  举报