2018.6清北学堂day2上午讲课(数论)

本文介绍了数论的基本概念,包括整除、素数、算术基本定理等内容,并详细讲解了素数判定方法、质因数分解算法及其实现方式。此外还探讨了欧几里得算法、裴蜀定理及其应用,以及逆元的概念和计算方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

QwQ

整除

对于整数n,mn,m,如果m!=0 且存在整数k,使得km=n,那么m就能整除n,记为m|nm|n

整除具有传递性a|b   b|c>a|ca|b   b|c−−>a|c

素数

素数有无限多个

素数定理
xx很大的时候,小于x的素数个数近似x/ln(x)

算术基本定理
任何一个大于1的正整数n
n=pr11prr22....n=p1r1∗pr2r2....

素数判定

解法1:
枚举2到nn的所有正整数
O(nn)

解法2:
枚举2到nn的所有素因子
O(n/lnxn/ln⁡x)

解法3:

Miller-Rabin算法

质因数分解

解法1:朴素求法

for (int i=1;i*i<=n;i++)
{
  if (n%i==0){
    d[++dsz]=i;
    if (i*i<n) d[++dsz]=n/2
  }
}

如果我们将n分解成n=pr11prr22....n=p1r1∗pr2r2....这种形式,那么nn的约数个数就通过乘法原理(r1+1)×(r2+1)....求出来


筛法

1.埃式筛法(线性筛的弱化版)

就是每个数标记它的倍数

for (int i=2;i<=n;i++)
{
  for (int j=i*2;j<=n;j+=i) check[j]=1;
}

调和剂数(QwQ貌似刚刚还是筛法呢)

1+12+13+14+....1n1+12+13+14+....1n=
1+12+12+14+14+14+14....1+12+12+14+14+14+14.... = log2nlog2⁡n

线性筛

理论依据,就是每一个数只会被自己的最小的质因子筛到
当 i 能整除 prime[j],那么 i*prime[j+1] 这个合数肯定被 prime[j] 乘以某个数筛掉。

for (int i=2;i<=n;i++)
{
   if (!check[i]) prime[++tot]=i;
   for (int j=1;j<=tot;j++)
   {
     if (i*prime[j]>n) break;
     check[i*prime[j]]=1;
     if (i%prime[j]==0) break;
   }
}

一个小题:给定n(n<10000)n(n<10000)个数,判定他们是素数和合数

解法:对于一个数xx,直接枚举[1,x]

另一道小题:
spoj prime1:
给定l,r(lr109,rl105),[l,r]l,r(l≤r≤109,r−l≤105),求[l,r]内的素数

解法:!!区间筛

1>把nn范围内的素数筛出来,然后把这些质数在区间内的倍数筛掉

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>

using namespace std;

inline int read()
{
  int x=0,f=1;char ch=getchar();
  while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
  while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
  return x*f;
}

const int maxn = 3e5+1e2;

int check[maxn];
int prime[maxn];
int n,m,l,r;
int tot;
int oi[maxn];


void primee(int n)
{
    check[1]=1;
    for (int i=2;i<=n;i++)
    {
        if (!check[i]) prime[++tot]=i;
        for (int j=1;j<=tot;j++)
        {
            if (i*prime[j]>n) break;
            check[i*prime[j]]=1;
            if (i%prime[j]==0) break;
        }
    }
}

void solve(int l,int r)
{
    for (int i=1;i<=tot;++i)
    {
        int p = prime[i];
        if (prime[i]>r) break;
        for (int j=(l-1)/p+1;j<=r/p;++j) if (p*j!=prime[i]) oi[p*j-l+1]=1;
    }
}

int t;

int main()
{
  primee(50000);
  cin>>t;
  //for (int i=1;i<=10;i++) cout<<prime[i]<<" "<<endl;
  while (t--)
  {
  memset(oi,0,sizeof(oi));
  l=read(),r=read();
  solve(l,r);
  if (l==1) oi[1]=1;
  for (int i=1;i<=r-l+1;++i)
  {
    if (!oi[i]) printf("%d\n",i+l-1);
  }
  cout<<"\n";
  }
  return 0;
}

}

QwQ欧几里得算法(gcd)

这里就不记笔记了

裴蜀定理

关于x,y的方程ax+by=cax+by=c 当且仅当gcd(a,b)|cgcd(a,b)|c可知有无穷多解,同时一定存在整数x,y使ax+by=gcd(a,b)ax+by=gcd(a,b)

引理:aab的线性组合集中最小的正元素是gcd(a,b)gcd(a,b)
引理:若a|bca,b=1a|ca|bc且(a,b)=1,则a|c

算术基本定理:

一些性质:
对于两个数m,nm,n

如果k=gcd(m,n)k=gcd(m,n)kp=min(mp,np)kp=min(mp,np)


如果k=lcm(m,n)k=lcm(m,n)

kp=max(mp,np)kp=max(mp,np)

小题:
hdu4497
给定三个数的gcd和lcm,求三元组个数(规定了三元组是有序的)

做法:

我们对于每个质因子单独考虑,假设当前的因子是p,那么p的次数一定是大于等于gcd中p的次数,小于等于lcm

因为三元组是有序的,所以我们考虑每两个数成为gcd和lcm的,另一个数在(pgcd,plcm)(pgcd,plcm)之间,那么这种时候就是6×rl16×(r−l−1),然后考虑有两个点在端点的情况,因为是对称的,所以最终答案就是6×(rl+1)+3+3=6×(rl)6×(r−l+1)+3+3=6×(r−l)

代码后补

拓展欧几里得

QwQ就是求解形如ax+by=gcd(a,b)ax+by=gcd(a,b)的方程

我们首先递归到底部,然后我们要求
ax+by=gcd(a,b)ax+by=gcd(a,b)

然后我们已知了是这个方程的解
bx1+(aa/bb)y1=gcd(b,amod b)bx1+(a−a/b∗b)y1=gcd(b,amod b)
进行一波操作
ay1+b(x1a/by1)ay1+b(x1−a/b∗y1)
所以x=y1,y=x1a/by1x=y1,y=x1−a/b∗y1

对于要求所以解的情况,我们只需要让x=x0+bgcd(a,b)x=x0+bgcd(a,b)
y=y0agcd(a,b)y=y0−agcd(a,b)


小题:noip2012同余方程
求关于 x 的同余方程 ax1(modb)ax≡1(modb) 的最小正整数解。

根据同余我们可以得到
ax+by=1ax+by=1
然后直接求解就行

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long

using namespace std;

long long a,b,x,y;

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

int main()
{
    scanf("%lld%lld",&a,&b);
    int ans=exgcd(x,y,a,b);
    cout<<(x+b)%b;
    return 0;
 } 

poj1061 青蛙的约会

NOI2002 荒岛野人

逆元

对于任意正整数a满足(a,m)=1,存在b满足ab1(modm)ab≡1(modm)

那么b就是a在%m意义下的逆元!

处理阶乘的逆元

q[1]=1;
for (int i=2;i<=n;i++) q[i]=q[i-1]*i%mod;
p[n]=qsm(q[n],mod-2);
for (int i=n;i>1;i--) p[i-1]=p[i]*i%mod;

O(n)O(n)预处理逆元!

假设我们要求的是i在mod p意义下的逆元

….后补

剩余类和完系
这里写图片描述

QwQ懒得记录了,还是后补吧

费马小定理

设p是一个素数,a是一个整数,且不是p的倍数,那么

ap11(modp)ap−1≡1(modp)

这里写图片描述

老师课件的简单的证明

可惜费马小定理的逆定理是不成立的

经测试,前10亿的自然数中,用费马小定理的逆定理验证素数,出错的概率是0.000025

QwQ那么我们怎么判断素数呢

这里引入二次探测定理

若p是素数,x是一个正整数,且x2mod p=1x2mod p=1 那么x±1(modp)x≡±1(modp)

这里写图片描述

听亢神的话

用2,7,61,24251做底数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值