声明:本文主要目的是供自己学习使用,部分来自OIWiki及学哥学姐指导,非本人原创。
数论
纯纯是研究理论数学的烧脑分支呀!!
让我们看看bing给出的定义:
初等数论主要就是研究整数环的整除理论及同余理论。此外它也包括了连分数理论和少许不定方程的问题。本质上说,初等数论的研究手段局限在整除性质上。
初等数论中经典的结论包括算数基本定理、欧几里得的质数无限证明、中国剩余定理、欧拉定理(其特例是费马小定理)、二次互反律, 勾股方程的商高定理、佩尔方程的连分数求解法等等。
我学的数论
本次集训接触数论是在最后一天,主要学习了如下内容:
1.素数定理
2.算数基本定理
3.整除理论
4.同余理论
5.乘法逆元
6.CRT
7.gcd,lcm,exgcd
8.exCRT
9.欧拉函数
10.莫比乌斯函数
11.Lucas定理
我只想记录已经完全学会的,所以本文持续更新(包括但不限于以上13类)
声明:以上的11个内容按照OI集训PPT顺序总结在下
一.素数定理
定义:素数,就是质数,它满足的性质是,只有1和它本身为它的公约数,也就是形如2,3,5……这样的数,规定:1不是素数,为什么呢?
1为什么不是素数:让我们看看一个叫整数分解定理的理论,请别问我为什么会学它。
对于任何一个整数m,有且仅有一组素数对(p1……pn)和正整数对(a1……an),使得m=p1^a1*......pn^an成立。
明白了吧。
对于1而言,分割方式有无限种,所以1虽然在素数定义处似乎没有什么破绽,但是到了整数分解定理这里,就显而易见了。
所以素数定理的内容是什么呢?
(令 π(n) 为小于等于 n 的素数个数,有 π(n)=Θ(n/lnn))
很是容易理解,所以不多说了。
二.算术基本定理
感觉这个就是上文的整数分解定理,但是不知道为什么学长为我们讲解了两次??
放个公式表达一下吧:
推出,素数的判定了
介绍四种方法:(思想就不介绍了OI数学必备)
1.定义O(√n)
//定义
for(int i = 1;i <= sqrt(n);i ++)
{
if(n % i == 0)
p[n] = 0;
}
p[n] = 1;
2.埃氏筛
//埃氏筛
for(int i = 2;i <= n;i ++)
p[i] = 1;
for(int i = 2;i <= n;i ++)
{
if(p[i])
for(int j = i * 2;j <= n;j += i)
p[j] = 0;
}
O(nloglogn)
3.欧拉筛
//欧拉筛
for(int i = 2;i <= n;i ++)
{
if(!vis[i])
p[pn ++] = i;
for(int j = 1;i * p[j] <= n;j ++)
{
vis[i * p[j]] = 1;
if(i % p[j] == 0)
break;
}
}
O(n)
4.我的筛法
三.整除理论
“人如其名”很理论化的东西,印象中除了gcd应该没有什么代码吧,所以直接搬运PPT
对于整数 a 和 b,若存在整数 q 使得 aq=b,那么称 a 为 b 的约数,b 是 a 的倍数。记作 a|b 。 a|b, b|c −> a|c
a|b, a|c −> a|s×b+t×c
a|b, b|a −>|a|=|b|
note:正负均可
———————————————————————————————————————————
设 a 和 b 是两个整数,如果 d | a 且 d | b,则称 d 是 a 与 b 的公因子
设 a 和 b 是两个不全为 0 的整数,称 a 与 b 的公因子中最大的为 a 与 b 的最大公因子, 或最大公约数,记作gcd(a,b) 或(a,b)
设 a 和 b 是两个非零整数,称 a 与 b 最小的正公倍数为 a 与 b 的最小公倍数,记作 lcm(a,b)或[a,b]
———————————————————————————————————————————gcd和lcm的性质
+
gcd代码
//gcd
int gcd(int x,int y)
{
return y == 0 ? x : gcd(y,x % y);
}
//O(log(a + b))
四.同余理论
整数 a,b 满足 m|a-b ,那么称 a 和 b 在模 m 下同余,记作 a ≡b (mod m)
对于 a ≡b (mod m) ,若 d|m ,则 a ≡b (mod d)
对于 a ≡b (mod m) ,若 d|m,d|a,d|b ,则 a/d ≡b/d (mod m/d)
对于 a ≡b (mod m) ,有 gcd(a,m)=gcd(b,m)
对于质数 m_1 和 m_2 ,若 gcd(m_1,m_2)=1 ,则 {m_2x_1+m_1x_2 mod m_1m_2|x_1,x_2∈ ℤ}= {x mod m_1m_2|x∈ ℤ}
exgcd
//exgcd
void exgcd(int a,int b,int &g,int &x,int &y)
{
if(!b)
x = 1;
y = 0;
g = a;
else
{
exgcd(b,a % b,g,y,x);
y -= x * (a / b);
}
}
//O(log(a + b))
如何证明??没有超出个人能力范围,但是真的要打好多字,所以上图
推论
乘法逆元,费马小定理,威尔逊定理
费马小定理:若 p 是质数,则对于任意整数 a 有 a^p=a (mod p)
威尔逊定理:若 p 是质数,则有 (p−1)!=−1 (mod p)
代码如何实现??
//线性推逆元
inv[1] = 1;
for(int i = 2;i <= p;i ++)
inv[i] = (p - p / i) * inv[p % i] % p;
//O(n)
CRT(中国剩余定理)※
内容:
引用学长原话:掌握思想即可,代码易于实现,所以就不给你们板子了。但是我理论是懂了,代码不会啊学长啊啊啊(悲)
在这里感谢OIWiki上的板子
//CRT
LL CRT(int k,LL* a,LL* r)
{
LL n = 1,ans = 0;
for(int i = 1;i <= k;i ++)
n = n * r[i];
for(int i = 1;i <= k;i ++)
{
LL m = n / r[i],b,y;
exgcd(m,r[i],b,y); // b * m mod r[i] = 1
ans = (ans + a[i] * m * b % n) % n;
}
return (ans % n + n) % n;
}
证明:还在研究……
拓展CRT
所谓“扩展CRT”“扩展中国剩余定理”,其实就是⽤exgcd⼀个个合并这些同余⽅程。
以合并两个同余⽅程
x ≡ b1 (mod m1)
x ≡ b2 (mod m2)
为例,
⽅程组有解的充要条件是(m1,m2)|(b1-b2), 此时x在模[m1, m2]意义下 有唯⼀解。 该⽅程组等价于 x = b1 + m1y1 x = b2 + m2y2 则b1 - b2 = m2y2 - m1y1,
exgcd求出y1、y2,可求出x在模[m1, m2]意义下的 唯⼀解 x =(b1 + m1y1)% [m1, m2]。
//excrt
#include<bits/stdc++.h>
#define int long long
#define LD long double
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int inf=2e18+100;
const int maxn=1e5+10;
int a[maxn],b[maxn];
int n;
int mul(int a,int b,int p)
{
int x=(LD)a*b/p;//#define LD long double
return ((a*b-x*p)%p+p)%p;//#define int long long
}
int exgcd(int a,int b,int &x,int &y)
{
if(b==0)
{
x=1;
y=0;
return a;
}
int gcd=exgcd(b,a%b,y,x);
y-=a/b*x;
return gcd;
}
int exc()
{
int prea=a[1],preb=b[1];
for(int i=2;i<=n;i++)
{
int x,y;
int d=exgcd(preb,b[i],x,y);
int t=b[i]/d;//如果 (a[i]-prea)%d!=0则无解
x*=(a[i]-prea)/d;
x=(x%t+t)%t;
int temp=preb/d*b[i];
prea=(preb*x+prea)%temp;
//prea=(mul(preb,x,temp)+prea)%temp;
preb=temp;
//prea=prea%preb;
}
return prea;
}
signed main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>b[i]>>a[i];
}
cout<<exc()<<"\n";
}
// __int128
/*
#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int inf=2e18+100;
const int maxn=1e5+10;
int a[maxn],b[maxn];
int n;
void print(__int128 x)
{
if (x>9) print(x/10);
putchar('0'+x%10);
}
__int128 exgcd(__int128 a,__int128 b,__int128 &x,__int128 &y)
{
if(b==0)
{
x=1;
y=0;
return a;
}
__int128 gcd=exgcd(b,a%b,y,x);
y-=a/b*x;
return gcd;
}
__int128 exc()
{
__int128 prea=a[1];
__int128 preb=b[1];
for(int i=2;i<=n;i++)
{
__int128 x,y;
__int128 d=exgcd(preb,b[i],x,y);
__int128 t=b[i]/d;
x*=(a[i]-prea)/d;
x=(x%t+t)%t;
__int128_t temp=preb/d*b[i];
prea=((preb%temp*x)%temp+prea)%temp;
preb=temp;
prea=prea%preb;
}
return prea;
}
signed main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>b[i]>>a[i];
}
print(exc());
}
*/
*/
欧拉函数
⼀个数x的欧拉函数φ(x)为⼩于x的正整数中与x互质的数的个数
特别地,φ(1) = 1。
性质
1.积性函数!
(什么是积性函数?) 积性函数:若对任意互质的两个数m和n有f(m*n)=f(m)*f(n),则 f(x)是积性函数。若对任意两个数(不要求互质)都有 f(m*n)=f(m)*f(n),则f(x)是完全积性函数。
2.对质数p, φ(p)=p-1。
3. ⼩于n的数中,与n互质的数之和为φ(n)*n/2 (n>1)。
4. n的所有因数的欧拉函数之和等于n
——————————