数论其一
一、质数
1.质数的定义:
如果一个正整数无法被除了1和它本身以外的任何自然数整除,那么这个数是质数。否则,这个数是合数。
需要注意的是,1既不是质数也不是合数。
2.埃筛:
2.埃筛:
问题:给定一个正整数
思路:我们可以从
时间复杂度
for(int i=2;i<=n;++i)
if(!vis[i])
for(int j=i*2;j<=n;j+=i)
vis[j]=1;
3.欧拉筛:
在埃筛中,一个合数会被多次标记,如6会被2和3分别标记一次。
而欧拉筛运用“每个合数只会被它的最小质因数筛一次”的思想,将时间复杂度降低到了
思路:设一个数组
for(int i=2;i<=n;++i){
if(v[i]==0)
v[i]=i,ans[++m]=i;
for(int j=1;j<=m;++j){
if(ans[j]>v[i]||ans[j]>n/i)
break;
v[i*ans[j]]=ans[j];
}
}
二、同余
1.定义:
如果整数
2.同余的性质:
(1)反身性:
(2)传递性:
(3)可加性:
(4)等幂性:
(5)可约性:
3.欧几里得算法与扩展欧几里得算法:
欧几里得算法:
证明:
若
若
对于
因此
证毕。
int gcd_(int a,int b){
if(b==0)
return a;
return gcd_(b,a%b);
}
扩展欧几里得算法:
前置知识:裴蜀定理:
证明:
在欧几里得定理的最后一步,即
假设存在一对正整数
我们把
也就是
证毕。
裴蜀定理的证明,实际上给出了整数
对于更为一般的方程
那么
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 tmp=x;x=y;y=tmp-a/b*y;
}
P1516 青蛙的约会
题目可以转化为
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 tmp=x;x=y;y=tmp-a/b*y;
}
signed main(){
scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&l);
a=n-m;b=x-y;
if(a<0)
a=-a,b=-b;
if(b<0)
b=(b+l)%l;
if(b%__gcd(a,l)!=0){
printf("Impossible\n");
return 0;
}
exgcd(a,l,t,t1);
t=b/__gcd(a,l)*t;
t=(t%(l/__gcd(a,l))+(l/__gcd(a,l)))%(l/__gcd(a,l));
printf("%lld\n",(t%l+l)%l);
return 0;
}
4.逆元
如果
逆元的求法1:扩展欧几里得
我们只要将同余柿子转化成
逆元的求法2:费马小定理
费马小定理:若
所以
注意:这种求法只适用于m是质数的情况。
逆元的求法3:线性算法
首先我们知道:
设
两边乘以
int main(){
scanf("%d%lld",&n,&P);
inv[1]=1;
for(int i=2;i<=n;i++)
inv[i]=(P-(P/i))*inv[P%i]%P;
for(int i=1;i<=n;++i)
printf("%lld\n",inv[i]);
return 0;
}
5.中国剩余定理和扩展中国剩余定理:
中国剩余定理:
设
则对于任意的
有整数解,解为
证明:
原方程组可以拆解成为n个方程组:
即:
此时原方程组的解为:
令
由题目可知,
所以
证毕。
ll exgcd(ll &x,ll &y,ll a,ll b){
if(b==0){
x=1;y=0;return a;
}
ll re=exgcd(x,y,b,a%b);
ll tmp=x;x=y;y=tmp-a/b*y;
return re;
}
int main(){
scanf("%lld",&n);
s=1;
for(int i=1;i<=n;++i){
scanf("%lld%lld",&a[i],&b[i]);
s*=a[i];
}
for(int i=1;i<=n;++i){
exgcd(x,y,s/a[i],a[i]);
x=s/a[i]*((x+a[i])%a[i])*b[i];
ans=(ans+x)%s;
}
printf("%lld\n",ans);
return 0;
}
扩展中国剩余定理:
还是求解中国剩余定理的方程组,但不保证
我们可以通过合并相邻方程的方式求解。
随便挑出两组方程:
我们把它转化为一般形式:
也就是:
其中,只有
根据裴蜀定理,如果
假设一组特解是
也就是
也就是
这样,我们就把两个方程合并成了一个方程。不断合并下去,就能求出原方程组的解。
ll mul(ll a,ll b,ll mod){
ll s=a;a=0;bool ok=0;
if(b<0)
b=-b,ok=1;
while(b){
if(b&1)
a=(a+s)%mod;
s=(s+s)%mod;b>>=1;
}
if(ok)
a=-a;
return a;
}
ll exgcd(ll a,ll b,ll &x,ll &y){
if(b==0){
x=1;y=0;return a;
}
ll re=exgcd(b,a%b,x,y);
ll tmp=x;x=y;y=tmp-y*(a/b);
return re;
}
ll excrt(){
ll y1=0,y2=0,x0=0,ans=0;
for(int i=2;i<=n;++i){
ans=exgcd(m[1],-m[i],y1,y2);
ll lcm=m[1]/__gcd(m[1],m[i])*m[i];
y1=mul(y1,m[1],lcm);
x0=(a[1]-mul(y1,(a[1]-a[i])/ans,lcm)+lcm)%lcm;
m[1]=lcm;a[1]=x0;
}
return x0;
}
int main(){
scanf("%lld",&n);
for(int i=1;i<=n;++i)
scanf("%lld%lld",&m[i],&a[i]);
printf("%lld\n",excrt());
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】