数论

1.exgcd

函数代码:

long long exgcd(long long a,long long b,long long&x,long long &y){
	if(b==0){
		x=1,y=0;
		return a;
	}
	long long d=exgcd(b,a%b,x,y);
	long long t=x;
	x=y;
	y=t-a/b*y;
	return d;
}

使用格式:

long long x,y,m,n,l;
	long long X,Y;
	long long x0;
	cin >> x >>y>>m>>n>>l;//解x+tm%l=y+tn%l的t ____x-y+tm-tn=kl(k,t正整数) 
	long long a=m-n;//(m-n)x0-ly0=y-x 求x0最小正整数
	long long b=-l;
	long long c=y-x;
	x0=exgcd(a,b,X,Y);//返回gcd
	if(c%x0!=0){//无解
		cout<<"Impossible";
	}
	else{ 
		b=b/x0;
		cout<<((X*(c)/x0)%b+b)%b;
	}

适用模式:

1.求解方程

解决形如ax+by=c的方程式

2.欧拉函数

函数代码:

int phi(int x){
	int ans=x;
	int i;
	for(i=2;i*i<=x;i++){
		if(x%i==0){
			ans=ans/i*(i-1);
			while(x%i==0){
				x/=i;
			}
		}
	}
	if(x>1){
		ans=ans/x*(x-1);
	}
	return ans;
}

使用格式:

直接用phi(x);

适用模式:

1.求解方程

对形如

\[a^x mod k \equiv 1 \]

的x求解———>先求phi(k),再枚举它的因子

2.求解有限制的gcd

不太好说,上例子


		//-----------------------------------------重点在这后面
		int ans=0;
//		for(int i=0;i<=ma;i++){
////			if(gcd(i,m)==1){
////				ans++;
////			}		
//		}//用欧拉函数代替一下 
		ans=phi(ma);
        //----------------------------------------重点在这前面


说白了就是把一堆gcd(i,m),m为定值的和进行o(1)求解

3.(ex)BSGS

函数代码:

long long BSGS(long long a,long long b,long long p,long long v=1){
	if(!a){
        if(!b) return 1;
        else return -1;
    }
	long long m =ceil(sqrt(p)),val=1,d;
	for(long long i=0;i<m;++i){
		long long pron=b*val%p;
		MP[pron]=i;
		val=val*a%p;
	}
	d=v*val%p;
	for(long long i=1;i<=m;++i){
		
		if(MP.count(d)){
			long long res=MP[d];
			return i*m-res;
		}
		d=d*val%p;
	}
	return -1;
}
long long exbsgs(long long a,long long b,long long p){
	if (b==1||p==1)return 0;
	long long t,c=0,v=1;
	while((t=gcd(a,p))!=1){
		if(b%t){
			return -1;
		}
		else{
			p/=t;
			b/=t;
			v=v*a/t%p;
			++c;
			if(b==v){
				return c;
			}
		}
	
	}	
		long long ret=BSGS(a,b,p,v);
		return ret!=-1?ret+c:ret;
}

使用格式:

直接套用即可

适用范围:

1.求解方程组

\[a^x\equiv b(mod p) \]

4.整数分块

代码:

long long fd{
	long long res=0;
	for(int l=1,r;l<=n;l=r+1){
		r=n/(n/l);
	}
}

用法:

1.简化时间复杂度

2.其中每一段,每一段的个数有r-l+1个,值为n/l;

5.莫比乌斯反演(思想)

代码:

m[1] = 1;
for(int i = 2; i <= n; i++){
    if(!k[i]){
        p[++t] = i;
        m[i] = -1;		
    }
    for(int j = 1; j <= t && p[j]*i <= n; j++){
        k[p[j]*i] = 1;
        if(i%p[j] == 0) break;
        m[i*p[j]] = -m[i];	
    }
}

用法:

常常会有$[gcd(i,j)=1]=所有gcd_{i,j}的因子的u之和。
直接用m[x]即可使用

目前遇到的大部分用法只有

逆元

网上看到了用法在这里

用法:

a/b%mod=a*(b的逆元)%mod.

代码:

求单个:(exgcd)
LL exgcd(LL a,LL b,LL &x,LL &y)//扩展欧几里得算法 
{
    if(b==0)
    {
        x=1,y=0;
        return a;
    }
    LL ret=exgcd(b,a%b,y,x);
    y-=a/b*x;
    return ret;
}
LL getInv(int a,int mod)//求a在mod下的逆元,不存在逆元返回-1 
{
    LL x,y;
    LL d=exgcd(a,mod,x,y);
    return d==1?(x%mod+mod)%mod:-1;
}

posted @ 2023-04-10 16:51  铃狐sama  阅读(26)  评论(0)    收藏  举报