约数与同余
约数与同余
质数
1.质数分布定理:在
2.判断n为质数的方法:试除法:(可以顺带求出约数集合)
int t=sqrt(n);
if(n<2)return false;
for(int i=2;i<=t;i++){
if(n%i==0)return false;
}
return true;
3.欧拉筛(线性筛质数):
int v[MAX_N],prime[MAX_N];
void primes(int n){
memset(v,0,sizeof v);
int cnt=0;//质数数量
for(int i=2;i<=n;i++){
if(!v[i]){
v[i]=i,prime[++cnt]=i;
}
for(int j=1;j<=cnt;j++){
if(prime[j]>v[i]||prime[j]*i>n)
break;
v[i*prime[j]]=prime[j];
}
}
for(int i=1;i<=cnt;i++)printf("%d ",prime[i]);
}
4.
约数
1.设
则
和为:
2.求
vector<int>factor[MAX_N];
for(int i=1;i<=n;i++){
for(int j=1;j<=n/i;j++){
factor[i*j].push_back(i);
}
}
时间复杂度为
推论:
gcd
定理
exgcd:
解决:求:
code:
int exgcd(int a,int b,int&x,int &y){
if(!b){
x=1,y=0;
return a;
}
int d=exgcd(b,a%b,x,y);
int z=x;
x=y,y=z-(a/b)*y;
return d;
}
欧拉函数
定义:
求法:
性质:
1.
2.若
3.在算术基本定理中
4.若
5.若
6.
欧拉函数的递推求解:
由性质4,5,我们可以在求质数的时候顺带求出欧拉函数
int v[MAX_N],prime[MAX_N],phi[MAX_N];
void euler(int n){
memset(v,0,sizeof v);
int cnt=0;
for(int i=2;i<=n;i++){
if(!v[i]){
v[i]=i;
prime[++cnt]=i;
phi[i]=i-1;
}
for(int j=1;j<=cnt;j++){
if(prime[j]>v[i]||i*prime[j]>n)break;
v[i*prime[j]]=prime[j];
phi[i*prime[j]]=phi[i]*(i%prime[j]?prime[j]-1:prime[j]);
}
}
}
同余
1.欧拉定理
推论:
当a,n不一定互质的时候有(扩展欧拉定理):
2.裴蜀定理: 对于任意整数a,b,存在一对整数x,y满足:
int exgcd(int a,int b,int&x,int &y){
if(!b){
x=1,y=0;
return a;
}
int d=exgcd(b,a%b,x,y);
int z=x;
x=y,y=z-(a/b)*y;
return d;
}
对于更加一般的一次不定方程
我们可以先用
由此我们可以设方程
乘法逆元
定义,设
求法:1.若n是质数,则
2.若仅仅是保证b,n互质,则d可通过求解线性同余方程求得
解线性同余方程
对于线性同余方程
中国剩余定理
设
则对于同余方程组:
有解,解为:
#include<iostream>
#include<cstdio>
#define int long long
using namespace std;
int exgcd(int a,int b,int &x,int &y){
if(!b){
x=1,y=0;
return a;
}
int d=exgcd(b,a%b,x,y),z=x;
x=y,y=z-(a/b)*y;
return d;
}
int n,M[100005],m[100005],t[100005],a[100005],M1=1;
int CRT(){
for(int i=1;i<=n;i++)M1*=m[i];
for(int i=1;i<=n;i++)M[i]=M1/m[i];
for(int i=1;i<=n;i++){
int x,y;
exgcd(M[i],m[i],x,y);
t[i]=x;
t[i]=(x%m[i]+m[i])%m[i];
}
int ans=0;
for(int i=1;i<=n;i++)ans+=M[i]*t[i]*a[i],ans%=M1;
return ans;
}
signed main(){
scanf("%lld",&n);
for(int i=1;i<=n;i++)scanf("%lld%lld",&m[i],&a[i]);
printf("%lld\n",CRT()%M1);
}
扩展中国剩余定理(excrt)
特别的,当
假设我们已经求出了前
高次同余方程:
拔山盖世(大步小步:Baby Step,Giant Step)算法
前提:a,p互质
因为a,p互质,所以可以在模p的意义下进行关于a的乘除运算
设
则方程式子可变为:
int BSGS(int a,int b,int p){
int t=sqrt(p)+1;b%=p,a%=p;
map<int,int>hash;hash.clear();
for(int i=0;i<t;i++){
hash[power(a,i,p)*b%p]=i;
}
a=power(a,t,p);
if(!a)return b==0?1:-1;
for(int i=0;i<=t;i++){
int m=power(a,i,p);
int j=hash.find(m)==hash.end()?-1:hash[m];
if(j>=0&&i*t-j>=0){
return i*t-j;
}
}
return -1;
}
exBSGS
:
int gcd(int a,int b){return !b?a:gcd(b,a%b);}
int exgcd(int a,int b,int &x,int &y)
{
if(!b)
{
x=1,y=0;
return a;
}
int gcd=exgcd(b,a%b,y,x);
y-=(a/b)*x;
return gcd;
}
inline int exBSGS(int a,int b,int mod)
{
b%=mod;
if(b==1||mod==1) return 0;
int g=0,val=1;
while(true)
{
int d=gcd(a,mod);
if(d==1) break;
if(b%d) return -1;
b/=d,mod/=d,val=val*a/d%mod;
g++;
if(b==val) return g;
}
int x,y;
exgcd(val,mod,x,y);
x=(x%mod+mod)%mod;
b=b*x%mod,a%=mod;
map<int,int>mp;
int t=ceil(sqrt(mod));
int z=1;
for(int i=0;i<t;i++)
mp[b*z%mod]=i,z=z*a%mod;
int p=1;
for(int i=1;i<=t;i++)
{
p=p*z%mod;
if(mp.count(p)) return i*t-mp[p]+g;
}
return -1;
}
signed main()
{
a=read(),p=read(),b=read();
while(a||b||p)
{
int ans=exBSGS(a,b,p);
if(ans==-1) puts("No Solution");
else printf("%lld\n",ans);
a=read(),p=read(),b=read();
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!