数论初步
约数相关
- 带余除法和整数
- 对于整数a,b,存在唯一的两个整数q,r使得\(b=aq+r(0<=r<=|a|)\)
- 同时可以得到\(b=\lfloor \frac{b}{a} \rfloor * a + b \mod a\)
- 当r=0时,我们称a整除b,记作\(a|b\)
- 此时也称b为a的倍数,a为b的约数
- 整除的性质
- \(a|c,b|c,(a,b)=1 \to ab|c\)
- \(a|bc,(a,b)=1 \to a|c\)
- \(p|ab \to p|a或p|b\)
- 素数与合数
- 若大于1的正整数P约数只有1和p本身,则称其为素数(质数)
- 若其有超过两个约数,则称其为合数
- 特别的,1不是质数
- 若两个数A,B最大公约数为1,则称A,B互质
- 算数基本定理
- 任何一个自然是N,可以唯一分解成有限个质数的乘积(在康托展开也有提到),式子表达为:\(N=\pi _ {i=1} ^ {m} p_i ^{k_i}\)
- 其中\(p_1<p_2<p_3<…<p_n\)
- 这样的分解称为N的标准分解式
小测验 #1
- 给定一个不超过\(10^{14}\)的正整数,如何计算其全部约数
long long a[N];
int cnt;
inline void ys(long long x){
int sx=sqrt(x);
if(x/sqrt(x)==sx)a[++cnt]=sqrt(x);//防止完全平方数出现两次
for(int i=1;i<sx;i++){
if(!(x%i)){
a[++cnt]=i;
a[++cnt]=x/i;
}
}
}
- 给定一个不超过\(10^{14}\)的正整数,如何计算其标准分解?
const int N=1e7+5;
int a[N],cnt;
inline void bzfj(long long x){
for(long long i=2;i*i<=x;i++){
if(!(x%i)){
a[++cnt]=i;
while(!(x%i))
x/=i;
}
}
if(x!=1){
a[++cnt]=x;
}
}
注:以上两篇代码都没有运行过,出锅了找我。
- 素数无限定理
- 正整数集中包含无限个素数
一些常用的复杂度常识
- 素数分布:\(lim_{n \to \infty} \frac {\pi (n) * ln n} {n}=1\)
- 调和级数:\(\sum _{1<=i<=n} \frac {N} {i}=O(N log n)\)
//调和级数循环举例
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
……
- 素数调和级数\(\sum {1<=p<=n} \frac {1} {i} =O(log^2n)\)
- 约数与倍数
- 对于a,b,如果\(d|a,d|b\),称d是a,b的公约数
- 对于其中最大的d,称d是a,b的最大公约数,记为\(d=(a,b)\)
- 对于a,b,如果\(a|d,b|d\),称d是a,b的公倍数
- 对于其中最小的d,称d是a,b的最小公倍数,记为\(d=[a,b]\)
- 集合含义
- GCD和LCM本质上是在研究两数的质因数分解的指数关系
- 两个很大的数,以标准分解形式给出,求其GCD?
- 两个很大的数,以标准分解形式给出,求其LCM?
- \(A=p_1^{a_1}*p_2^{a_2}*…*p_n^{a_n},B=p_1^{a_1}*p_2^{a_2}*…*p_n^{a_n}\)
- 因为
太简单了不会写,所以直接口胡 - \(GCD=\pi _ {i=1}^{n}p_i^{min(a_i,b_i)}\)
- \(LCM=\pi _ {i=1}^{n}p_i^{mix(a_i,b_i)}\)
- 欧几里得算法
- 算最大公约数
- \((a,b)=(a-b,b)=(a \mod b,b)\)
- 复杂度分析(分类讨论a<b与a>b,每次一定/2所以复杂度为\(log n\))
- 裴蜀定理
裴蜀定理(或贝祖定理)得名于法国数学家艾蒂安·裴蜀,说明了对任何整数a、b和它们的最大公约数d,关于未知数x和y的线性不定方程(称为裴蜀等式):若a,b是整数,且gcd(a,b)=d,那么对于任意的整数x,y,ax+by都一定是d的倍数,特别地,一定存在整数x,y,使ax+by=d成立。 --百度百科
- \(\forall a,b,d,(a,b)|d等价于\exists u,v \in N,ua+vb=d\)
- 判断二元一次方程无解
- 【例题1】【模板】裴蜀定理
inline int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
int n,ans=0;
int main(){
read(n);
for(int i=1,x;i<=n;i++){
read(x);
if(x<0)x=-x;
ans=gcd(ans,x);
}
printf("%d",ans);
return 0;
}
【例题2】瓶子和燃料
int n,k,ans=0;
//从n个数里选出k个数,求这k个数最大的gcd
map<int,int>mp;//数据太大,防止RE
int main(){
read(n);read(k);
for(int i=1,x;i<=n;i++){
read(x);
for(int j=1;j*j<=x;j++){
if(x%j)continue;
mp[j]++;
int y=x/j;
if(j!=y)mp[y]++;
if(mp[y]>=k)ans=max(ans,y);
if(mp[j]>=k)ans=max(ans,j);
}
}
printf("%d",ans);
return 0;
}
- 扩展欧几里得算法
/*void exgcd(int a,int b,int &x,int &y){
if(b==0){x=1,y=0;return ;}
exgcd(b,a%b,x,y);
int t=x;
x=y;
y=t-(a/b)*y;
}*/
void exgcd(int a,int b,int &x,int &y){
if(b==0){x=1,y=0;return ;}
exgcd(b,a%b,y,x);
y-=(a/b)*x;
}
- 同余
- 若\(a=b(\mod p)\),则存在整数k使得\(a=b+kp\)
- \(a=b(\mod p)<=>p|b-a\)
- \(a=b(\mod p),a=b(\mod q)<=>a=b(\mod [p,q])\)
- \((k,p)=d,ka=kb(mod p)<=>a=b(\mod \frac {p} {d})\)
->同余方程\(x=a_1(\mod m_1);x=a_2(\mod m_2)\) - 何时有解?\(gcd(m_1,m_2)|(a_1-a_2)\)
- 通解如何表示?设其中一个特解为x0则\(x=x_0+k*lcm(m_1,m_2)\)为通解
- 最小正整数解\(x=(x%b+b)%b\)
【例题1】青蛙的约会
【例题2】荒岛猎人
12.快速幂与快速乘(不应该是龟速乘吗(雾)
//普通快速幂
inline int qpow(int a,int b,int mod){
int res=1;
while(b){
if(b&1)res=a*res%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
struct Matrix{
int a[N][N];
Matirx(){
memset(a,0,sizeof a);
}
inline void build(){
for(int i=1;i<=n;i++)
a[i][i]=1;
}
}a,ans;
Matrix operator * (const Matrix &x,const Matrix &y){
Matrix res;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
for(int k=1;k<=n;k++){
res.a[i][j]=res.a[i][j]+x.a[i][k]*y%mod;
}
}
}
return res;
}
signed main(){
read(n);read(k);
for(int i=1;i<=n;i++){
for(int j=1;j<-n;j++){
read(a.a[i][j]);
}
}
ans.build();
while(k){
if(k&1)ans=ans*a;
a=a*a;
k>>=1;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
printf("%d",ans.a[i][j]);
}
puts("");
}
}

浙公网安备 33010602011771号