数论和数学

数论和数学

数论
欧几里得算法:快速计算两数最大公约数

对于两个正整数\(m,n(m>n)\)\(gcd(m,n)\)表示它们的最大公约数,有\(gcd(m,n)=gcd(n,m\ mod\ n)\)

证明:

\[\begin{align} &设gcd(m,n)=p,m=p\cdot m_1,n=p\cdot n_1\\ &设m=k\cdot n+r\\ &m\ mod \ n=r=p\cdot m_1-k\cdot n=p\cdot m_1-p\cdot k\cdot n_1=p(m_1-k\cdot n_1)\\ &∵gcd(m_1,n_1)=1\\ &∴gcd(m_1-k\cdot n_1,n_1)=1\\ &∴gcd(n,m\ mod\ n)=p \end{align} \]

根据这个性质,就可将\(m,n\)不断转换直到其中一个为0,另一个就是最大公约数

代码:

int gcd(int m,int n)
{
    if( n==0 ) return m;
    else return gcd(m,m%n);
}
拓展欧几里得算法:对方程\(ax+by=c\)进行快速求解

裴蜀定理:方程\(ax+by=c\)有整数解当且仅当\(gcd(a,b)|c\)

证明:

\[\begin{align} &设gcd(a,b)=p,a=p\cdot a',b=p\cdot b'\\ &p(a'x+b'y)=c\\ &∵a',x,b',y都是整数\\ &∴p|c即gcd(a,b)|c \end{align} \]

如果方程\(ax+by=c\)有整数解,那么根据裴蜀定理和欧几里得算法可以得出\(bx+(a\ mod\ b)y=c\)也有整数解

\[\begin{align} &设a=k\cdot b+r\\ &设bx+ry=c的整数解为x_1,y_1\\ &bx_1+ry_1=c\\ &bx_1-k\cdot by_1+ay_1=c\\ &b(x_1-ky_1)+ay_1=c\\ &即方程ax+by=c的整数解为y_1,x_1-ky_1 \end{align} \]

根据这个可以不停进行转化直到方程变为\(ax=c\)

代码:

void exgcd(int a,int b)
{
    if( b==0 )
    {
        x=c/a;
        y=0;
        return;
    }
    exgcd(b,a%b);
    int z=x;
    x=y;
    y=z-y*(a/b);
    return;
}
乘法逆元

若有\(x\cdot y\equiv1(mod\ p)\)则记\(y=x^{-1}\)\(x\)在模\(p\)意义下的乘法逆元

拓展欧几里得算法求逆元:

\[\begin{align} &x\cdot y\equiv1(mod\ p)\\ &x\cdot y-k\cdot p=1\\ &即y和-k是关于a,b的方程ax+bp=1的两个整数解,运用拓展欧几里得算法即可求得 \end{align} \]

Eratosthenes 筛法

从2扫到n,如果没有被标记,那么这个数就是素数,将它在n以内的倍数都打上标记

代码:

int prime[N];
bool flag[N];

void Prime(int n)
{
    for(int i=2;i<=n;i++)
        if( !flag[i] )
        {
            prime[++prime[0]]=i;
            for(int j=2;j*i<=n;j++) flag[i*j]=1;
        }
    return;
}
欧拉筛法

在线性时间复杂度内求出n以内的素数

在Erathosthenes筛法的基础上进行改进,我们保证每一个合数只被它最小的质因子筛掉,我们记录每一个数的最小质因子,然后不断更新即可

int prime[N],mprime[N];

void Prime(int n)
{
 	for(int i=2;i<=n;i++) mprime[i]=i;
    for(int i=2;i<=n;i++)
    {
        if( mprime[i]==i ) prime[++prime[0]]=i;
        for(int j=1;j<=prime[0] && prime[j] <= mprime[i];i++)
            mprime[prime[j]*i]=prime[j];
    }
    return;
}
数学
快速幂

把指数二进制分解,快速算出\(a^x\)

代码:

int fpow(int a,int b)
{
    int ans=1,base=a;
    while( b )
    {
        if( b%2 ) ans*=base;
        base*=base;
        b/=2;
    }
    return ans;
}
数学期望

每一种情况的概率和权值相加

线性代数
矩阵

从上到下进行消元得到一个上三角矩阵,然后将对角线乘积相加就得到行列式的值

高斯消元

从上到下进行消元然后在从下到上带回去

代码:

int Gauss(int equ,int var)
{
	for(int i=0; i<=var; i++)
	{
		x[i]=0;
		freeX[i]=true;
	}

	int col=0;
	int row;
	for(row=0; row<equ&&col<var; row++,col++)
	{
		int maxRow=row;
		for(int i=row+1; i<equ; i++) 
		{
			if(abs(a[i][col])>abs(a[maxRow][col]))
				maxRow=i;
		}
		if(maxRow!=row)
		{
			for(int j=row; j<var+1; j++)
				swap(a[row][j],a[maxRow][j]);
		}
		if(a[row][col]==0)
		{
			row--;
			continue;
		}

		for(int i=row+1; i<equ; i++)
		{
			if(a[i][col]!=0)
			{
				int lcm=LCM(abs(a[i][col]),abs(a[row][col]));
				int ta=lcm/abs(a[i][col]);
				int tb=lcm/abs(a[row][col]);
				if(a[i][col]*a[row][col]<0)
					tb=-tb;
				for(int j=col; j<var+1; j++)
				{
					a[i][j]=a[i][j]*ta-a[row][j]*tb;
				}
			}
		}
	}

	for(int i=row; i<equ; i++)
		if (a[i][col]!=0)
			return -1;

	int temp=var-row;
	if(row<var)
		return temp;

	for(int i=var-1; i>=0; i--)
	{
		int temp=a[i][var];
		for(int j=i+1; j<var; j++)
		{
			if(a[i][j]!=0)
				temp-=a[i][j]*x[j];
		}
		if(temp%a[i][i]!=0)
			return -2;
		x[i]=temp/a[i][i];
	}
	return 0;
}
组合数学
二项式定理
image-20200409203748791

相当于在n个(x+y)中选k个为x,n-k个为y

斯特林数

第一类Stirling数表示将 n 个不同元素构成m个圆排列的数目

递推式:

image-20200409204238701

第二类Stirling数实际上是集合的一个拆分,表示将n个不同的元素拆分成m个集合的方案数

递推式:

image-20200409204327912
微积分

留个坑

猜你喜欢

转载自www.cnblogs.com/BZDYL/p/12817995.html