数论(待完善)

快速幂

typedef long long ll;
ll binaryPow(ll a, ll b, ll m) {
	ll ans = 1;
	while (b > 0) {
		if (b & 1) {
			ans = ans * a % m;
		}
		a = a * a % m;
		b >>= 1;
	}
	return ans;
}

唯一分解定理
打印素数表之后,遍历素数表,能除就一直除,加一个统计就行,如果过大就停止就行。

逆元
对于缩系中的元素,每个数a均有唯一的与之对应的乘法逆元x,使得ax≡1(mod n)
一个数有逆元的充分必要条件是gcd(a,n)=1,此时逆元唯一存在
逆元的含义:模n意义下,1个数a如果有逆元x,那么除以a相当于乘以x。
除一个数就等于乘这个数的逆元,模意义下似乎是不能用除法的

模的逆解线性同余方程组
ak≡1(mod m)
则对于ax≡b(mod m)两边同乘k->x=bk

费马小定理
gcd(a,p)=1 则ap-1≡1(mod p)
也就是a*ap-2≡1(mod p) ap-2是a模p的一个逆

欧几里得算法

int gcd(int a,int b){
	return b == 0 ? a : gcd(b, a%b);
}

gcd和lcm
在这里插入图片描述
由唯一分解定理可得,lcm(a,b)gcd(a,b)=ab。
注意已知gcd和a*b求lcm这种记得先除避免爆了。

素数定理
小于或等于x的素数个数,称为π(x),随着x增大,有:
π(x)≈x/ln(x)

扩展欧几里得算法
也就是在原先求gcd的基础上,还求出了gcd(a,b)=ax+by中的x y
先看一个推导
ax+by=bx-(a%b)y
=bx+(a-int(a/b)b)y
=ay+b(x-int(a/b)y)
现在的等式两边的x y是不一样的,分别对应一组x y的解,那x y就可以这样一组解一组解的依次转化,而我们可以直到当它一直向下递归的时候一定能达到x=1,y=0的这组解,所以我们就可以得到所有解了

int exGcd(int a,int b,int &x,int &y)
{
    if(b==0)
    {
        x=1;y=0;
        return a;
    }
    int r=exGcd(b,a%b,x,y);
    int t=x;x=y;y=t-a/b*y;
    return r;
}

求逆元的几种方法求乘法逆元的几种方法
exgcd求逆元
用扩展欧几里得算法求得一组x0,y0和gcd
检查gcd是否为1
gcd不为1则说明逆元不存在
若为1,则调整x0到0~m-1的范围中即可

exgcd求ax=c(mod b)的x的最小整数解
我们可以用扩展欧几里得算法得出ax+by=gcd(a,b) 的一组解(x1,y1),那么其他解呢?任取另一组解(x2,y2),则ax1+by1=ax2+by2(因为它们都等于gcd(a,b) ),变形得a(x1-x2)=b(y2-y1)。假设gcd(a,b)=g,方程左右两边同时除以g(如果g=0,说明a或b等于0,可以特殊判断),得a’(x1-x2)=b’(y2-y1),其中a’=a/g,b’=b/g。注意,此时a’和b’互素(想想分数的化简),则因此x1-x2一定是b’的整数倍(因为a’中不包含b’,所以x1-x2一定包含b’)。设它为kb’,计算得y2-y1=ka’。注意,上述的推导过程并没有用到“ax+by的右边是什么”,因此得出以下结论:

设a,b,c为任意整数,若方程ax+by=c的一组解是(x0,y0),则它的任意整数解都可以写成(x0+kb’,y0-ka’),其中a’=a/gcd(a,b),b’=b/gcd(a,b),k取任意整数。

int cal(int a,int b,int c)
{
	int x,y;
	int gcd=(a,b,x,y);
	if(c%gcd!=0)
		return -1;//代表无解 
	//  ax0+by0=gcd(a,b)                                方程一 
	//同时乘以c/gcd(a,b)得   
	// (a*c/gcd(a,b))*x0+(b*c/gcd(a,b))*y0=c;
	// 令 x1=c/gcd(a,b)*x0  y1=c/gcd(a,b)*y0;
	// 则可得 ax1+by1=c                                 方程二 
	// 这时得出方程的一个解   x1=x0*c/gcd(a,b)     y1=y0*c/gcd(a,b)  
	x*=c/gcd; //将 方程一的一个特解转化成方程2的一个特解 
	//套用上文的公式可得对方程二
	// b'=b/gcd(a,b);
	b/=gcd;   
	if(b<0)//处理小于0的特殊情况 
		b=-b;
	//对特解x  +- kb'  找到最小整数解
	//设x=kb'+r
	//那么我们想要求的整数解就是r
	//直接取模运算即可 
	int ans=x%b; 
	//把负数的r转化成正数的 
	if(ans<=0)
		ans+=b;
	return ans;
}
https://blog.csdn.net/weixin_42165981/article/details/81185418

线性同余方程组
1.两个以上不同模的一元线性同余方程
2.变元数大于1,方程数大于1,但方程模相同
对于1问题可以用中国剩余定理
对于2问题可以用高斯消元法

中国剩余定理
对于不同模的一元线性方程组
x≡a1(mod m1)
x≡a2(mod m2)
····
x≡ar(mod mr)
有M=m1m2····*mr

那我就令Mi=m1* m2*··· *mi-1 *mi+1 *···*mr yi为其逆元
则x=a1M1y1+a2M2y2+····+arMryr(mod M) 且唯一(有两解可推相等)
因为对于任意mod mi,mi | Mk(k!=i) 而对于aiMiyi, Miyi=1
所以x就是解

int china(int r)
{
    M=1;
    for(int i=1; i<=r; i++)
        M*=m[i];
    for(int i=1; i<=r; i++)
    {
        Mi=M/m[i];
        extend(Mi,m[i],d,X,Y);
        ans=(ans+Mi*X*a[i])%M;
    }
    if(ans<0)
        ans+=M;
    return ans;
}

当然也可以用迭代法,就是和普通算数一样,就一个方程一个方程带

//多项式同余方程

欧拉函数
对正整数n,欧拉函数是小于或等于n的正整数中与n互质的数的数目

欧拉定理
aφ(n)≡1(mod n)
用既约剩余系证明
由此又可以得出求逆的方法,aφ(n)-1即为a的逆

定理1:若p为素数 则φ§=p-1 逆定理亦然
定理2:p是素数 a是正整数φ(pa)=pa-pa-1(不超过pa且能被p整除的即kp(1<=k<=pa-1)
定理3:设m n互素,则φ(mn)=φ(m)φ(n) 积性函数
定理4:设n=p1a1p2a2···pnan为正整数n的唯一分解式,则φ(n)=n(1-1/p1)(1-1/p2)···(1-1/pn)
利用定理2对每个质因子单独考虑p1a1->p1a1-1(p1-1)=p1a1(1-1/p1)
乘起来就是答案
定理5:n的所有因子d的φ(d)加起来为n

筛法
思想很简单,对于不超过n的非负整数p,删除2p,3p,4p····,当处理完所有数之后,还没有被删除的就是素数。
但这做了很多无用功。
下面给出对其的三次优化
1.第一层循环只需要到n1/2就行,比如n=10000,那对于一个100-10000的数,如果一个因子在100-10000,另一个因子一定<100。
2.增加vis数组不仅仅用于标记,还用于判重,因为第一层循环可能循环到比如4,那我在2的时候就已经标记过4了,所以跳过。
3.第二层循环的开始从i2开始,比如第一层循环为3,那么13和23在前面一定已经标记过了,所以只需要从此开始就行。

int m=sqrt(n+0.5);
	memset(vis,0,sizeof(vis));
	for(int i = 2; i<= m; i++) if(!vis[i])
	for(int j = i*i; j<=n; j+=i) vis[j]=1;

然而埃筛是有缺陷的:对于一个合数,有可能被筛多次,所以我们限定只用某一个数的最小质因子取筛选即可,即为欧拉筛

线性筛 欧拉筛

int prime[maxn];
int visit[maxn];
void Prime(){
    mem(visit,0);
    mem(prime, 0);
    for (int i = 2;i <= maxn; i++) {
        if (!visit[i]) {
            prime[++prime[0]] = i; //这个prime[0] 相当于 cnt,用来计数
        }
        for (int j = 1; j <=prime[0] && i*prime[j] <= maxn; j++) {
            visit[i*prime[j]] = 1;
            if (i % prime[j] == 0) {
                break;
            }
        }
    }
}

这里是把i当作要乘的数,也就是用素数表中的数取乘i,然后i % prime[j] == 0就是当 i是prime[j]的倍数时,i = k*prime[j],如果继续运算 j+1,i * prime[j+1] = prime[j] * k prime[j+1],这里prime[j]是最小的素因子,当i = k * prime[j+1]时会重复,所以才跳出循环。不只是对于prime[j+1],往后都可以在i=kprime[j+m]中被更小的质因子prime[j]更新

线性筛求积性函数
求欧拉函数

int prime[maxn];
int vis[maxn];
int phi[maxn];
void Prime() {
    memset(vis, 0, sizeof(vis));
    memset(prime, 0,sizeof(prime));
    for (int i = 2; i <= maxn; i++) {
        if (!vis[i]) {
            prime[++prime[0]] = i; 
            phi[i] = i - 1;
        }
        for (int j = 1; j <= prime[0] && i * prime[j] <= maxn; j++) {
            vis[i * prime[j]] = 1;
            if (i % prime[j] == 0) {
                phi[i * prime[j]] = phi[i] * prime[j];//phi[p^k]=(p-1)*p^(k-1),i中已经*了p-1,那后面只需一直除乘p就行了,可以想象递推的过程
                break;
            }
            else phi[i * prime[j]] = phi[i] * (prime[j] - 1);//i中无p,*(p-1)即phi[prime[j]]
        }
    }
}

排列组合

集合的排列就高中题
集合的循环排列就是围成一个圆的排列,就拿n去除线性排列的数目即可

A(n,r)=r!(n r)逻辑上非常好理解
那么(n,r)=n!/r!(n-r)!

多重集的排列
S是一个多重集,有k个不同类型的元素,各元素的重数分别为n1,n2,···nk,则S的排列数为n!/n1!n2!····*nk!
就是有nk个元素相同,那位置互换也相同,所以除掉

多重集的组合
也就是x1+x2+···+xk=r的非负整数解个数 xi取无限
那我们就先解决正整数解个数,就是用隔板法就是C(r-1,k-1)
然后非负整数解就是令yi=xi+1 然后再用隔板法就是C(r+k-1,k-1)=(r+k-1,r)

x1+x2+x3+x4=20的整数解个数 x1>=3,x2>=1, x3>=0, x4>=5
那就分别用不同的yi去替换就行了

Pascal公式
C(n, k) = C(n - 1, k - 1) + C(n - 1, k)
结合实际意义推导就是对于第n个物品,要么选要么不选。加一块就是了
当然也可以直接算,也简单
预处理二项式系数就用Pascal公式递归

for (int i = 0; i <= n; i++) {
			for (int j = 0; j < i + 1; j++) {
				if (i == j || j == 0) {
					arr[i][j] = 1;
				} else {
					arr[i][j] = arr[i - 1][j - 1] + arr[i - 1][j];
				}
			}
			

两个恒等式
C(0,m)+C(1,m)+···+C(n,m)=C(n+1,m)
kC(n,k)=nC(n-1,k-1)

多项式定理
(x1+x2+x3+···+xk)n=∑n!/(n1!*n2!n3!···*nk!)x1n1x2n2···xnnk

组合数计算
在数据范围比较小的时候我可以用pascal公式O(n2)计算
但是比较大就需要用组合数公式C(n,m)=n!/(m!(n-m)!)
先预处理阶乘fact[i]=fact[i-1]*i
然后令分母等于k,计算k mod p的逆元,然后快速幂求解O(logn)即可
也可以采用递推方式
也可以Lucas定理
111这里大佬博客有详解

容斥原理

S中不具有P1P2···Pn的物体个数
也就是S-∑|Ai|+∑|Ai∩Aj|····奇减偶加这样
至少具有一个就拿全集再去减这个就行
还有|A∪B|=|A|+|B|-|A∩B|奇加偶减

高斯消元法

解多元方程组,也就是把方程组写成矩阵形式,然后把系数矩阵变成上三角矩阵再依次推出答案
https://blog.csdn.net/lzyws739307453/article/details/89816311

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
牙科就诊管理系统利用当下成熟完善的SSM框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的Mysql数据库进行程序开发。实现了用户在线查看数据。管理员管理病例管理、字典管理、公告管理、药单管理、药品管理、药品收藏管理、药品评价管理、药品订单管理、牙医管理、牙医收藏管理、牙医评价管理、牙医挂号管理、用户管理、管理员管理等功能。牙科就诊管理系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。 管理员在后台主要管理病例管理、字典管理、公告管理、药单管理、药品管理、药品收藏管理、药品评价管理、药品订单管理、牙医管理、牙医收藏管理、牙医评价管理、牙医挂号管理、用户管理、管理员管理等。 牙医列表页面,此页面提供给管理员的功能有:查看牙医、新增牙医、修改牙医、删除牙医等。公告信息管理页面提供的功能操作有:新增公告,修改公告,删除公告操作。公告类型管理页面显示所有公告类型,在此页面既可以让管理员添加新的公告信息类型,也能对已有的公告类型信息执行编辑更新,失效的公告类型信息也能让管理员快速删除。药品管理页面,此页面提供给管理员的功能有:新增药品,修改药品,删除药品。药品类型管理页面,此页面提供给管理员的功能有:新增药品类型,修改药品类型,删除药品类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值