【模板】数学

同余

逆元

线性递推

inv[1]=1;
for(int i=2;i<=n;++i)	inv[i]=p-inv[p%i]*(p/i)%p,inv[i]%=p;

快速幂

inv[i]=ksm(i,p-2,p)

阶乘递推

inv[n]=ksm(po[n],p-2,p);//po[i]是i的阶乘
for(int i=n-1;i;--i)  inv[i]=inv[i+1]*(i+1)%p;

高次同余方程

大小步(BSGS)

点击查看代码
int bsgs(int a,int b,int p){//(a^x)%p=b%p 
	map<int,int> ha;
	int t=sqrt(p)+1;
	for(int i=0,q=b%p;i<t;++i,q=q*a%p)	ha[q]=i;
	int w=ksm(a,t,p);
	for(int i=1,q=w;i<=t;++i,q=q*w%p)
		if(ha.find(q)!=ha.end())	return t*i-ha[q];
	return -1;
}

拓展大小步(EX-BSGS)

点击查看代码
int bsgs(int a,int b,int p,int ad){
	unordered_map<int,int> ha;
	int t=sqrt(p)+1;
	for(int i=0,j=b%p;i<t;++i,j=j*a%p)	ha[j]=i;
	int w=ksm(a,t,p);
	for(int i=1,j=ad*w%p;i<=t;++i,j=j*w%p)
		if(ha.find(j)!=ha.end())	return i*t-ha[j];
	return -1;
}
int exbsgs(int a,int b,int p){
	a%=p,b%=p;
	int cnt=0,ad=1,t;
	if(b==1 || p==1)	return 0;
	while((t=__gcd(a,p))!=1){
		if(b%t!=0)	return -1;
		++cnt,b/=t,p/=t,ad=ad*(a/t)%p;
		if(ad==b)	return cnt;
	}
	t=bsgs(a,b,p,ad);return (t==-1?-1:t+cnt);
}

中国剩余定理

CRT

点击查看代码
int CRT(){
	int m=1,res=0,x,y;
	for(int i=1;i<=n;++i)	m*=a[i];
	for(int i=1;i<=n;++i){
		int tmp=m/a[i];
		exgcd(tmp,a[i],x,y);
		res=(res+tmp*x*b[i]%m)%m;
	}
	return (res%m+m)%m;
}

EX-CRT

点击查看代码
const int N=1e5+5;
int a[N],b[N],n;
int exgcd(int a,int b,int &x,int &y){
	if(!b){x=1,y=0;return a;}
	int g=exgcd(b,a%b,x,y),t=x;
	x=y,y=t-a/b*y;
	return g;
}
int excrt(){
	int A=a[1],B=b[1];
	for(int i=2;i<=n;++i){
		int k1,k2;
		int g=exgcd(A,a[i],k1,k2);
		if((b[i]-B)%g!=0)	return -1;
		k1*=(b[i]-B)/g;
		k1=(k1%(a[i]/g)+(a[i]/g))%(a[i]/g);
		B=k1*A+B,A=(A*a[i])/g;
	}
	return B%A;
}

欧拉定理

拓展欧拉定理

注意快读写法!

记住!\(n\) 小于 \(\phi(p)\) 的时候不能加 \(\phi(p)\)

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int cnt=0;
namespace IOBuf{
	char gc(){
		static char buf[100000],*p1=buf,*p2=buf;
		return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
	}
	int read(int p){
		int sum=0,f=1;char a=gc();cnt=0;
		while(a<'0' || a>'9'){if(a=='-')f=-1;a=gc();}
		while(a>='0' && a<='9')	sum=sum*10+a-'0',cnt|=(sum>=p),sum%=p,a=gc();
		return (sum*f%p+p)%p;
	}
	void print(int x){
		if(x<0)	putchar('-'),x=-x;
		if(x>9)	print(x/10);
		putchar(char(48+x%10));
	}
}
using namespace IOBuf;
int ksm(int x,int y,int p){
	int res=1;
	while(y){if(y&1)res=res*x%p;y>>=1,x=x*x%p;}
	return res%p;
}
signed main(){

	int a=read((int)1e10),p=read((int)1e10),n;
	int pi=1;int t=p;
	for(int i=2;i*i<=p;++i){
		if(p%i!=0)	continue;
		pi*=(i-1),p/=i;while(p%i==0)pi*=i,p/=i;
	}
	if(p>1)	pi*=(p-1);
	n=read(pi);
	if(cnt)	n+=pi;
	print(ksm(a,n,t));

	return 0;
}

线性代数

消元

高斯消元

点击查看代码
void Guass(){
	for(int i=1;i<=n;++i){
		int ma=i;
		for(int j=i+1;j<=n;++j)if(fabs(a[j][i])>fabs(a[ma][i]))ma=j;
		if(i!=ma)	swap(a[i],a[ma]);
		if(fabs(a[i][i])<eps){cout<<"No Solution\n";return;}
		d div=a[i][i];
		for(int j=i;j<=n+1;++j)	a[i][j]/=div;
		for(int j=i+1;j<=n;++j){
			div=a[j][i];
			for(int k=i;k<=n+1;++k)	a[j][k]-=div*a[i][k];
		}
	}
	for(int i=n;i;--i){
		ans[i]=a[i][n+1];
		for(int j=i-1;j;--j)a[j][n+1]-=(a[j][i]*ans[i]);
	}
	for(int i=1;i<=n;++i)printf("%.2lf\n",ans[i]);
}

高斯-约旦 消元

点击查看代码
void Guass_Jordan(){
	for(int i=1;i<=n;++i){
		int ma=i;
		for(int j=i+1;j<=n;++j)if(fabs(a[j][i])>fabs(a[ma][i]))ma=j;
		for(int j=1;j<=n+1;++j)swap(a[i][j],a[ma][j]);
		// cout<<ma<<" : ";
		if(fabs(a[i][i])<eps){cout<<"No Solution";return;}
		for(int j=1;j<=n;++j){
			if(j==i)	continue;
			for(int k=i+1;k<=n+1;++k)a[j][k]-=a[i][k]*a[j][i]/a[i][i];
		}
	}
	for(int i=1;i<=n;++i)printf("%.2lf\n",a[i][n+1]/a[i][i]);
}

约数

拓展欧几里得定理(exgcd)

点击查看代码
int exgcd(int a,int b,int &x,int &y){
	if(!b){x=1,y=0;return a;}
	int g=exgcd(b,a%b,x,y),t=x;
	x=y,y=t-a/b*y;
	return g;
}

线性筛法求欧拉函数

点击查看代码
void init(int n){
	for(int i=2;i<=n;++i){
		if(!vi[i])	pr[++co]=i,phi[i]=i-1;
		for(int j=1;j<=co && i*pr[j]<=n;++j){
			vi[pr[j]*i]=1;
			if(i%pr[j]==0){
				phi[pr[j]*i]=phi[i]*pr[j];
				break;
			}
			else	phi[i*pr[j]]=phi[i]*(pr[j]-1);
		}
	} 
}
posted @ 2022-11-16 20:46  _yolanda  阅读(47)  评论(0编辑  收藏  举报