【数学一本通】[总结] 第一章 数论

第一章:数论

知识点:

(就只整理了蒟蒻自己学的比较深刻的东西)

1.gcd
2.同余
3.最大公约数

1.辗转相除法(gcd板子)

LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);}

2.二进制优化gcd(好像用的不是很多,还是写一下吧)

LL gcd(LL x,LL y)
{
	int i,j;
	if(!x) return y; if(!=y) return x;
	for(i=0;0==(x&1);i++) x>>=1;//去掉所有的2
	for(j=0;0==(y&1);i++) y>>=1;//去掉所有的2
	if(j<i) i=j;
	while(1)
	{
		if(x<y) x^=y, y^=x,x^=y;//若x<y交换x,y
		if(0==(x-=y)) return y<<i;
//若x==y,gcd==x==y(就是在辗转减,while(1)控制)
		while(0==(x&1)) x>>=1;//去掉所有的2
	}
}

3.最小公倍数: L C M ( x , y ) = x ∗ y ÷ g c d ( x , y ) LCM(x,y) = x * y \div gcd(x,y) LCM(x,y)=xy÷gcd(x,y)
4.扩展欧几里得算法(exgcd板子)

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

5.解线性同余方程

	LL t=gcd(a,b);
	if(c%t!=0) printf("NO solution\n");
	a/=t; b/=t; c/=t;
	exgcd(a,b,x,y);
	x=((c*x)%b+b)%b;
	printf("%lld\n",x);
4. 逆元

快速幂求逆元:

LL ksm(LL a,LL b,,LL key)
{
	LL tmp=b;
	for(;a;a>>=1,tmp=(tmp*tmp%key)) if(a&1) tmp=(tmp*b%ket);
	return tmp;
}

exgcd求逆元:

	LL a,b,x,y;
	exgcd(LL a,LL b,LL x,LL y);
5.中国剩余定理(china板子)

板子题:【模板】扩展中国剩余定理(EXCRT)

#include<bits/stdc++.h>
#define ll long long 
#define sea 1100000
using namespace std;
ll m[sea],aa[sea],ans,n;
template<typename T>inline void read(T &x)
{
	x=0;T f=1,ch=getchar();
	while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getchar();}
	while(isdigit(ch))  {x=x*10+ch-'0';  ch=getchar();}
	x*=f;
}
ll hhhhhh(ll a,ll b,ll mod)
{
    ll res=0;
    while(b>0)
    {
        if(b&1)  res=(res+a)%mod;
        a=(a+a)%mod;
        b>>=1;
    }
    return res;
}
ll exgcd(ll a,ll b,ll &x,ll &y)
{
	if(b==0){x=1;y=0;return a;}
	ll gcd=exgcd(b,a%b,x,y);
	ll tp=x;
	x=y; y=tp-a/b*y;
	return gcd;
}
ll  china()
{
	ll x,y;
	ll M=m[1],ans=aa[1];
	for(ll i=2;i<=n;i++)
	{
		ll a=M,b=m[i],c=((aa[i]-ans)%b+b)%b;
		ll gcd=exgcd(a,b,x,y),bg=b/gcd;
//		if(c%gcd!=0) return -1;
		x=hhhhhh(x,c/gcd,bg);
		ans+=x*M;
		M*=bg;
		ans=(ans%M+M)%M;
	}
	return (ans%M+M)%M;
}
int main()
{
	read(n);
	for(ll i=1;i<=n;i++) 
	read(m[i]),read(aa[i]);
	printf("%lld",china());
	return 0;
}
6.斐波那契数

由于好好的手推了一下通项公式,觉得比矩阵快速幂快多了,
F ( n ) = 5 5 [ ( 1 + 5 2 ) n − ( 1 − 5 2 ) n ] F_{(n)}=\frac{\sqrt{5}}{5}[(\frac{1+\sqrt{5}}{2})^{n}-(\frac{1-\sqrt{5}}{2})^{n}] F(n)=55 [(21+5 )n(215 )n]
代码中的通项:
x = k ⋅ ( − 1 ) i f ( i − 1 ) x=k⋅(−1)^if(i-1) x=k(1)if(i1) y = k ⋅ − 1 i + 1 i f ( i − 2 ) y=k⋅-1^i+1^if(i-2) y=k1i+1if(i2)

    for(int p0=1, p1=1, x=0, y=1; p0+p1<=n; p1=p0+p1, p0=p1-p0, x=y-x, y=y-x)
    {
        tx=1ll*x*n, ty=1ll*y*n;
        fx=tx%p1; if(fx<=0) fx+=p1; fy=ty-(fx-tx)/p1*p0;
        sy=ty%p0; if(sy<=0) sy+=p0; sx=tx-(sy-ty)/p0*p1;
        if(fy<=0||sx<=0) break;
        ans=(ans+(sx-fx)/p1+1)%1000000007;
    }
    printf("%d",ans);
7.卡特兰数

公式:
1.递推公式 1:
f ( n ) = ∑ i = 0 n − 1 f ( i ) × f ( n − i − 1 ) f(n)=\sum_{i=0}^{n-1} f(i)×f(n-i-1) f(n)=i=0n1f(i)×f(ni1)
2.递推公式 2:
f ( n ) = f ( n − 1 ) × ( 4 n − 2 ) n + 1 f(n)=\frac{f(n-1)×(4n-2)}{n+1} f(n)=n+1f(n1)×(4n2)
3.组合公式 1:
f ( n ) = C 2 n n n + 1 f(n)=\frac{C^n_{2n}}{n+1} f(n)=n+1C2nn
4.组合公式 2:
f ( n ) = C 2 n n − C 2 n n − 1 f(n)=C^n_{2n}-C^{n-1}_{2n} f(n)=C2nnC2nn1

int main()
{
	scanf("%d",&n);
	catlan[0]=catlan[1]=1;
	for(int i=2;i<=n;i++)
	for(int j=0;j<i;j++)
	catlan[i]=((catlan[j]*catlan[i-j-1])%mod+catlan[i])%mod;
	printf("%lld",catlan[n]);
	return 0;
}
8.解高次同余方程(BSGS板子)
#include<bits/stdc++.h>
#define LL long long
using namespace std;
LL A,B,C,ans,D,y,x,m,t;
class hash 
{
	public:
    hash(){memset(a,0xff,sizeof(a));}
    int locate(LL x)
	{
        LL l=x%MOD;
        while(a[l]!=x&&a[l]!=-1) l=(l+1)%MOD;
        return l;
    }
    void insert(LL x,LL va)
	{
        LL l=locate(x);
        if(a[l]==-1) a[l]=x,v[l]=va;
    }
    LL get(LL x) 
	{
       LL l=locate(x);
        return a[l]==x?v[l]:-1;
    }
    void clear(){memset(a,0xff,sizeof(a));}
	private:
    static const LL MOD=100007;
    LL a[MOD+100],v[MOD+100];
}H;
LL exgcd(LL a,LL b,LL &x ,LL &y)
{
	LL t,s;
	if(!b){x=1,y=0; return a;}
	s=exgcd(b,a%b,x,y);
	t=x,x=y,y=t-a/b*y;
	return s;
}
int main()
{
	while(scanf("%lld%lld%lld",&C,&A,&B)!=EOF)
	{
		H.clear();
		m=ceil(sqrt(double(C))); t=1;
		for(int i=0;i<m;i++) H.insert(t,i),t=t*A%C;
		D=1; ans=-1;
		for(int i=0;i<m;i++)
		{
			exgcd(D,C,x,y);//exgcd求逆元
			x=((x*B)%C+C)%C;///B*x=B*D^(-i*m)
			y=H.get(x);//匹配即可
			if(y!=-1){ans=i*m+y; break;}
			D=(D*t)%C;///D=t^i,(t=A^m)
		}
		if(ans==-1) printf("no solution\n");
		else printf("%lld\n",ans);
	}	
	return 0;	
} 
9.欧拉函数的线性筛
#include<stdio.h>
#define LL long long
using namespace std;
const int sea=1000001;
int a[sea],b[sea],f[sea],k,x;
LL s[sea];
void xxs()
{
	int n=sea,i,j;
	for(i=2;i<=n;i++) a[i]=0;
	for(i=2;i<=n;i++)
	{
		if(a[i]==0) a[i]=i,b[++k]=i;
		for(int j=1;j<=k&&i*b[j]<=n;j++) 
		{
			a[i*b[j]]=b[j];
			if(i%b[j]==0) break;
		}
	}	
	f[1]=1;
	for(i=2;i<=n;i++)
	if(a[i/a[i]]==a[i]) f[i]=f[i/a[i]]*a[i];
	else f[i]=f[i/a[i]]*(a[i]-1);
	for(i=2;i<=n;i++) s[i]=s[i-1]+f[i];
}
int main() 
{
	xxs();
	while(scanf("%d",&x)!=EOF) 
	{
		if(x==0) break; 
		printf("%lld\n",s[x]);	
	} 
	return 0;
}

大概就是这样吧,总的来说,这次跟着数学一本通对数论进行系统的学习,其实还是蛮好的,比较完整的学习了一些知识。
所以还是比较推荐学习这本书的。
下面打算接着往下学一章,没有按照顺序,就是想学什么就学什么,那下一章就矩阵吧。

continue……

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值