数学知识
数学知识
1. 判定质数、分解质因数(试除法)
时间复杂度
bool is_prime(int n){
if(n<2)return false;
for(int i=2;i*i<=n;i++)
if(n%i==0)return false;
return true;
}
2. 质数筛法(线筛)
时间复杂度
int v[N],p[N],cnt=0;
viod primes(int n)
{
memset(v,0,sizeof v);
for(int i=2;i<=n;i++)
{
if(!v[i])p[++cnt]=i;
for(int j=1;j<=cnt&&p[j]*i<=n;j++)
{
v[p[j]*i]=1;
if(i%p[j]==0)break;
}
}
}
3. 约数个数 和 约数之和
算法基本定理的推论
若正整数被分解为,其中都是正整数,都是质数,且满足
则的整约数集合可写作:
的正约数个数为:
的所有正约数个数的和为:
4. 欧几里得算法
//求
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
5. 求欧拉函数(朴素、筛法)
欧拉函数
1~N中与N互质的数的个数被称为欧拉函数,记为。
若在算法基本定理中,,则:
证明:
性质1~2
积性函数
性质3~6
筛法
#define ll long long
ll p[N],v[N],phi[N],cnt=0;
void init(int x)
{
for(int i=2;i<=x;i++)
{
if(!v[i])p[++cnt]=i,phi[i]=i-1;
for(int j=1;j<=cnt&&p[j]*i<=x;j++)
{
v[p[j]*i]=1;
if(i%p[j]==0)phi[i*p[j]]=phi[i]*p[j];
else phi[i*p[j]]=phi[i]*(p[j]-1);
if(i%p[j]==0)break;
}
}
}
6. 快速幂
#define ll long long
ll init(ll x,ll y)
{
ll res=1;
while(y)
{
if(y&1)res*=x;
x*=x;y>>=1;
}
return res;
}
7. 扩展欧几里得
定理
//求出特解的代码
#define ll long long
void exgcd(int a,int b,int &x,int &y)
{
if(b==0)
{
x=1,y=0;
return a;
}
int d=exgcd(b,a%b,y,x);
y-=(a/b)*x;
return d;
}
求通解
对于一般方程,它有解当且仅当d|c。
所以在用上述代码求解后,我们可以得到一组特解(c/d),(c/d)
通解可表示为:
8. 逆元
费马小定理
若正整数a,n互质,则
乘法逆元
若整数b,p互质,并且b|a,则存在一个整数x,使得。称x为b的模m的乘法逆元,记为。
因为,所以
如果p是质数并且b<p,由费马小定理得,因此,当模数p为质数时,即为b的乘法逆元。
9. 中国剩余定理/扩展
设是两两互质的整数,,是线性同余方程的一个解。对于任意的n个整数,方程组
有整数解,解为。
#define ll long long
ll n,m=1;
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(b==0){x=1,y=0;return a;};
ll d=exgcd(b,a%b,y,x);
y-=(a/b)*x;
return d;
}
ll get(ll a,ll b,ll p)
{
ll res=0;
while(b)
{
if(b&1)res=(res+a)%p;
a=(a+a)%p;
b>>=1;
}
return res;
}
int main()
{
scanf("%lld",&n);
ll ans=0,x,y,d,a,b,c;
ll a0,m0;
for(int i=1;i<=n;i++)
{
scanf("%lld%lld",&a,&b);
if(i==1)
{
a0=a,m0=b;
continue;
}
d=exgcd(a0,a,x,y);
c=((b-m0)%a+a)%a;
x=get(x,abs(c/d),a/d);
m0=x*a0+m0;
a0=(a0/d)*a;
}
ans=(m0%a0+a0)%a0;
printf("%lld",ans);
return 0;
}
10. 矩阵乘法
定义
设是矩阵,是矩阵,则是矩阵,并且:
//矩阵乘法满足结合律,满足分配律,不满足交换律
单位矩阵
矩阵快速幂
#define ll long long
ll n,k;
ll A[N][N],mod=1e9+7;
void multi(ll c[][N],ll a[][N],ll b[][N])
{
ll tmp[N][N]={0};
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
for(int s=1;s<=n;s++)
tmp[i][j]+=a[i][s]*b[s][j]%mod,tmp[i][j]%=mod;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
c[i][j]=tmp[i][j]%mod;
}
}
void init(ll k)
{
ll res[N][N]={0};
for(int i=1;i<=n;i++)
res[i][i]=1;
while(k)
{
if(k&1)
{
multi(res,res,A);
}
multi(A,A,A);
k>>=1;
}
}
11. 高斯消元
高斯消元法,是线性代数中的一个算法,可用来求解线性方程组,并可以求出矩阵的秩,以及求出可逆方阵的逆矩阵。
原线性方程组 ——> 高斯消元法 ——> 下三角或上三角形式的线性方程组 ——> 前向替换算法求解(对于上三角形式,采用后向替换算法)
思路如下:
解为:
求解步骤
-
将当前要求的未知数系数绝对值最大的一行交换到上面;
-
将不包括该行在内的下面所有行该未知数的系数都化为这个最大的系数;
-
以下所有行都减去该行;
-
换下一个未知数,然后重复操作;
-
显然,当做完一轮这样的操作后,下面的所有行里当前未知数的系数都为 0,也就是少了一个未知数;
如果对整个矩阵都这样操作过后,最终得到的矩阵一定是一个倒三角(梯形)的形状; -
做完一轮以上操作,再从下往上扫,如果有解,则最后一行的方程一定是 axn=b(a≠b),则 xn 可以解出,再代回上一个方程即可解出 xn−1。以此类推,就可以解出所有解;
解的情况
-
无解
在正推或倒推的时候,如果出现形如 0=b(b≠0) 的式子,则方程一定无解;
-
无数解
在正推或倒推时,都没有出现无解的情况;
正推和倒推过程中产生的不是 0=0 这样的式子不足 n 个; -
唯一解
正推和倒推过程中没有无解现象;
最后剩下的不是 0=0 的式子恰好 n 个;
int n,id[N];
double ans[N],b[N],a[N][N];
int get_max(int i,int tmp)
{
double maxx=0;tmp=0;
for(int j=i;j<=n;j++)
if(fabs(a[id[j]][i])>maxx)
{
maxx=abs(a[id[j]][i]);
tmp=j;
}
return tmp;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
scanf("%lf",&a[i][j]);
scanf("%lf",&b[i]);
id[i]=i;
}
for(int i=1;i<=n;i++)
{
int tmp=get_max(i,tmp);
if(tmp==0)
{
printf("No Solution\n");
return 0;
}
swap(id[tmp],id[i]);
for(int j=i+1;j<=n;j++)
{
a[id[i]][j]/=a[id[i]][i];
}
b[id[i]]/=a[id[i]][i];
a[id[i]][i]=1;
for(int j=i+1;j<=n;j++)
{
double t=a[id[j]][i]/a[id[i]][i];
a[id[j]][i]=0;
for(int k=i+1;k<=n;k++)
{
a[id[j]][k]-=t*a[id[i]][k];
}
b[id[j]]-=t*b[id[i]];
}
}
for(int i=n-1;i>=1;i--)
{
for(int j=n;j>i;j--)
{
b[id[i]]-=a[id[i]][j]*b[id[j]];
a[id[i]][j]=0;
}
}
for(int i=1;i<=n;i++)
{
printf("%.2f\n",b[id[i]]);
}
return 0;
}
12. 求组合数(递推、公式、预处理逆元、lucas定理)
-
加法原理:
若完成一件事有n种方法,第i种方法有种方案,且事件之间互不影响,则一共有种方案 -
乘法原理:
若完成一件事有n个步骤,第i个步骤有种方案,且这些步骤互不干扰,则一共有种方案 -
排列数
从n个不同元素中依次取出m个元素排成一列,产生的不同排列的数量为:
- 组合数
从n个不同元素中依次取出m个组成一个集合(不考虑顺序),产生的不同集合数量为:
-
性质
-
Lucas定理
若p是质数,则对于任意整数,有:
也就是把n和m表示成p进制数,对p进制下的每一位分别计算组合数,最后再乘起来。
- Catalan数列
给定n个0和n个1,它们按照某种顺序排成长度为2n的序列,满足任意前缀0的个数都不少于1的个数的序列的数量为:
推论:
以下问题都与Catalan数有关:
1.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步