【知识】 数论

    数论,是信息学竞赛中很重要的一个知识点。最近学习了数论的一些经典问题与算法,还是写写博客总结一下。

    1.整除(简单又基本)

    定义:设a、b为整数,且b不等于0,若存在整数p使得a=b*p,那么称b整除a,记为b|a

    性质:

    1)如果a|b,b|c,那么a|c

    2)如果a|b,a|c,那么a|(kb+lc) (k、l为整数)

    3)如果a|b,那么ma|mb (m≠0)

    4)如果存在整数x、y,使得ax+by=1,且a|n,b|n,那么ab|n(因为如果存在x、y满足条件,那么a、b互质,之后的便不难理解)

    2.gcd与lcm(较简单)

    定义:gcd:最大公约数,lcm:最小公倍数

    性质:lcm(a,b)=a*b/gcd(a,b)

    计算方式:

    因为lcm可以转化为gcd,我们可以只求gcd

    我们设a>b,gcd(a,b)=d。我们将a表示为k*b+p,那么d|(k*b+p)、d|b,所以d|p,也就是d|(a%b),因此d也是(a%b)的约数,但d是不是b与(a%b)的最大公约数呢?如果不是,那么一定存在一个更大的d'|b且d'|(a%b),那么d'|a,与d是a,b的最大公约数相矛盾。所以:gcd(a,b)=gcd(b,a%b)这就是欧几里得算法

    3.勾股数(有一些难度)

    定义:若存在整数x、y、z,使得x^2+y^2=z^2,那么称(x,y,z)为一组勾股数,如果x、y、z可以由一组勾股数分别乘上一个数得到,那么就称之为派生勾股数,否则叫基本勾股数,基本勾股数满足gcd(x,y,z)=1

    性质:

    基本勾股数的奇偶性:

    1)三个偶数

    明显不行,因为如果是三个偶数,至少是派生的,可以一起除以2

    2)三个奇数

    也不行,奇数平方=奇数,奇数+奇数≠奇数

    3)一奇两偶

    不行,不管是偶+偶还是奇+偶都无法得到合法解(偶+偶≠奇,奇+偶≠偶)

    4)两奇一偶

    唯一的方法,如果x奇y奇,那么x=2k+1,y=2p+1,x^2=4k^2+4k+1,y^2=4p^2+4p+1,那么(x^2+y^2)%4=2,无法开方,所以勾股数必定是奇+偶=奇!

    计算方法:x=m,y=(m^2/k-k)/2,z=(m^2/k+k)/2,

    ① 当m确定为任意一个≥3的奇数时,k={1,m^2的所有小于m的因子}
    ② 当m确定为任意一个 ≥4的偶数时,k={m^2 / 2的所有小于m的偶数因子})

    4.素数(质数)(较简单)

    定义:因子只有1与本身的数称为素数

    判断素数:O(sqrt(n))

    枚举2~sqrt(n),如果都不是n的因子,那么n是素数

    筛素数:

    一般方法:

int vis[MAXN];
int prime[MAXP]
void sieve(int n)
{
	int m=(int)sqrt(n+0.5); //浮点数四舍五入,最好在后面加一个0.5。
	memset(vis,0,sizeof(vis));
	for(int i=2;i<=m;i++)
	if(!vis[i])
		for(int j=i*i;j<=n;j+=i)
			vis[j]=1;

    极速方法(巧妙运用循环):

int prime[MAXP];
bool flag[MAXN];
int j=0;
for(int i=2;i<=n;i++)
{
	if(flag[i]==0)
	prime[j++]=i;
	for(int k=0;k<j;k++)
	{
		if(prime[k]*i>n)break;
		flag[prime[k]*i]=1;
	if(i%prime[k]==0)break;
	}
}


    5.同余

    定义:如果a%n=b%n,称a与b关于n同余,写作a≡b(mod n)

    性质:

    1.自反性:a≡a(mod m)
    2.对称性:若a≡b(mod m),则b≡a(mod m)
    3.传递性:若a≡b(mod m),b≡c(mod m),则a≡c(mod m)
    4.同加性:若a≡b(mod m),则a+c≡b+c(mod m)
    5.同乘性:若a≡b(mod m),则a*c≡b*c(mod m),若a≡b(mod m),c≡d(mod m),则有a*c≡b*d(mod m)
    6.同幂性:若a≡b(mod m),则an≡bn(mod m)

    7.若a%p=x,a%q=x,且p,q互质,则a%(p*q)=x

    三大分配率:

    加法分配率:(a+b)%n=(a%n+b%n)%n
    减法分配率:(a-b)%n=(a%n-b%n)%n
    乘法分配率:(a*b)%n=a%n*b%n%n

    相关定理:

    1)威尔逊定理:如果p为质数,(p-1)!≡-1(mod p)

    证明:p为质数,1~p-1全在p的缩系中,除了1和p-1与自己配对,其他两两与别的数配对后%p=1,那么(p-1)!只剩下p-1和1,相乘后%p=p-1

    2)欧拉定理(费马小定理含于欧拉定理):如果a与m互质,a^φ(m)≡1(mod m)

    证明:设φ(m)=p,这个证明,无非是证明a^p%m=1。我们已经知道,对于一个整数都会有缩系,而欧拉函数刚好(或是专门)用来求一个数的缩系中元素个数。我们可以将a^p乘上m的缩系中的每个元素,转化为如下形式:(a*k1%m+a*k2%m+a*k3%m+...+a*kp%m)%m,而对于不相等的i和j,且a与m互质,有:a*ki%m≠a*kj%m且它们都在m的缩系中,那么原式的值也等于(k1*k2*k3*...*kp)%m,即a^p*k1*k2*k3*...*kp≡k1*k2*k3*...*kp(mod m),由缩系的定义,我们可以得知:k1*k2*k3*...*kp与m互质,那么两边同时除以一个k1*k2*k3*...*kp,就有了a^p%m=1

    相关:

    求欧拉函数

    1.求单个欧拉函数

int euler(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);
}
    2.求1~n所有欧拉函数
int phi[maxn];
void phi_table(int n)
{
	phi[1]=1;
	for(int i=2;i<=n;i++)
		if(!phi[i])
			for(int j=i;j<=n;j+=i)
			{
				if(!phi[j])
					phi[j]=j;
				phi[j]=phi[j]/i*(i-1);
			}
}

    3)扩展欧几里得定理:ax+by=gcd(a,b)一定有解,可以求出这个解

    证明:设d=gcd(a,b),因为ax+by=d一定有解,d=gcd(a,b)=gcd(a,a%b),所以bx1+a%b*y1=d也一定有解,以下是证明过程:

    bx1+a%b*y1=d =>

    bx1+(a-a/b*b)*y1=d =>

    bx1+ay1-a/b*b*y1=d =>

    ay1+b*(x1-a/b*y1)=d

    根据原式:ax+by=d,显然:当x=y1,y=x1-a/b*y1时一定是一组解,那么递归求解即可

    相关:

    求解二元一次方程

    ax+by=c,显然只有c=k*d(gcd(a,b))时才有解,算出ax+by=d时的解,然后c是d的几倍,x和y就乘以几,解答完毕……

   求解模线性方程

   ax≡b(mod n),转化一下,变成ax+ny≡k*d(即gcd(a,n))(mod n)(当然,b如果不是d的倍数自然无解),我们可以求出ax+ny≡d(mod n)时的一个x,然后将它乘上k求出一个解。那么怎么求最小的x(x0)呢?显然:

    ax+ny≡b =>

    ax+l+ny-l≡b =>

    a(x+l/a)+n(y-l/n)≡b

    所以,l如果是a、n的公倍数,要使得l最小,那l就是a、n的最小公倍数,即a*n/d。对于a而言,x就加上了一个a*n/d/a即n/d,那么只要不停加或减n/d得到的x,都是方程的解所以x0=(x%(n/d)+n/d)%n/d,就可以顺利解答所有情况了!

    未完待续。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值