数论学习笔记——同余、欧拉函数、素数、欧拉定理、费马小定理

注:本文正处于未完待续状态

  • [同余 ]

同余的性质:(%m-->(mod m))

1.a≡a%m

2.if a≡b%m,then b≡a%m

3.if a≡b%m,b≡c%m,then a≡c%m

4.if a≡b%m,then a+c≡(b+c)%m

5.<1>if a≡b%m,then ac≡bc%m

<2>if a≡b%m,c≡d%m,then ac≡bd%m

<3>if a≡b%m,then ac≡bc%(mc)

6.if gcd(c,m)=1,then when ac≡bc%m,a≡b%m

7.if a≡b%m,then an≡bn%m

8.(Coro 1):ab%k=(a%k*b%k)%k

9.if gcd(p,q)=1,a%p=x,a%q=x,then a%(p*q)=x

  • [素数 ]

1.素数有无限个

证明
假设素数的个数有限,将所有素数相乘得到整数p,p+1不能被前述任何素数整除,则p+1也是一个素数,与假设矛盾。

2.唯一分解定理:任何一个大于1的正整数都能被唯一分解为有限个素数的乘积,可写作N=p\(1\)c1 *p\(2\)c2...p\(m\)cm,其中c\(i\)都是正整数,p\(i\)都是素数且满足p\(1\)<p\(2\)<...<p\(m\)

3.N中最多只能含有一个大于$ \sqrt{n}$的因子--反证法

4.判定素数

code
bool is_prim(int x)
{
  if(x==1)return 0;
  for(int i=2;i*i<=x;i++)
    if(x%i==0)return 0;
  return 1;
}

5.筛素数(线性筛法)

code
void get_prim(int n)
{
  for(int i=2;i<=n;i++){
    if(!vis[i])prim[++cnt]=i;
    for(int j=1;i*prim[j]<=n;j++){
      vis[i*prim[j]]=1;
      if(i%prim[j]==0)break;
    }
  }
}
  • [欧拉函数]

1.通项公式为:φ(n)=n×(1-$ \frac{1}{pi}$)(i=1~k),其中p为n所有质因数,n为正整数

2.性质

<1>φ(1)=1;

<2>若p是一个素数,则φ(p)=p-1

<3>若p是一个素数,则φ(pk)=(p-1)×pk-1

<4>欧拉函数为积性函数:对于任意两个正整数a,b,且gcd(a,b)=1,则φ(a×b)=φ(a)×φ(b)

变形:<1>若n%p=0,则φ(n×p)=p×φ(n)

<2>p为素数,若n%p≠0,则φ(n×p)=(p-1)×φ(n)

<3>当n为奇数时,φ(2n)=φ(n)

<4>与n互质的数都是成对出现的,且每队的和为n,所以大于2的数的φ(n)都为偶数

3.试除法求欧拉函数

code
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;
}
4.求1~n所有欧拉函数值(继续线性筛)
code
void get_phi(int n)
{
	phi[1]=1;
	for(int i=2;i<=n;i++)
	{
		if(!vis[i])
		{
			prime[++cnt]=i;
			phi[i]=i-1;
		}
		for(int j=1;i*prime[j]<=n;j++)
		{
			int m=i*prime[j];
			vis[m]=1;
			if(i%prime[j]==0)
			{
				phi[m]=prime[j]*phi[i];
				break;
			}
			else phi[m]=(prime[j]-1)*phi[i];
		}
	}
}
5.求约数个数与约数和(还是线性筛orz)

n=p\(1\)r1 * p\(2\)r2 ... p\(k\)rk

n的约数个数为d(n)=(r\(1\)+1)×(r\(2\)+1)×...×(r\(k\)+1)

d[i]记录i的约数个数

num[i]记录i的最小质因数个数

code
void get_primes(int n)
{
	d[1]=1;
	for(int i=2;i<=n;i++)
	{
		if(!vis[i])
		{
			prime[++cnt]=i;
			d[i]=2;
			num[i]=1;
		}
		for(int j=1;i*prime[j]<=n;j++)
		{
			int m=i*prime[j];
			vis[m]=1;
			if(i%prime[j]==0)
			{
				d[m]=d[i]/(num[i]+1)*(num[i]+2);
				num[m]=num[i]+1;
				break;
			}
			else
			{
				d[m]=d[i]*2;
				num[m]=1;
			}
		}
	}
}
posted @ 2025-02-07 16:19  Crab2016  阅读(35)  评论(0)    收藏  举报