只是单纯记录一下结论和自己的理解,太菜了,证明只能看大佬博客(哭
1.裴蜀定理:对于给定的正整数a,b,方程ax+by=c有解的充要条件为c是gcd(a,b)的整数倍。
定理的推广: 方程ax+by+cz+…+nm=f(其中a,b,c…n,f为整数)有解的充要条件是f为gcd(a,b,c,…,n)的整数倍。
2.扩展欧几里得算法:可以求出两个整数x,y,使其满足ax+by=d,d为gcd(a,b).在此前提下使|x|+|y|最小,算法可以求出一组特解,通解为:
x
=
x
+
k
∗
b
d
y
=
y
−
k
∗
a
d
x=x+k*\frac{b}{d}\qquad y=y-k*\frac{a}{d}\quad
x=x+k∗dby=y−k∗da
利用该算法还可求逆元,求a在模p下的逆元,代入exgcd(a,p,d,x,y),如果gcd(a,b)!=1,则不存在逆元。否则逆元为(x+p)%p。
void exgcd(ll a,ll b,ll&d,ll& x,ll& y)
{
if(!b)
{
d=a,x=1,y=0;
}
else
{
exgcd(b,a%b,d,y,x);y-=x*(a/b);
}
}
3.欧拉phi函数:phi(x)表示小于x且与x互质的数的个数。推导利用了容斥定理,还是需要理解一下的。结论:
p
h
i
(
n
)
=
n
∗
(
1
−
1
p
1
)
∗
(
1
−
1
p
2
)
.
.
.
∗
(
1
−
1
p
k
)
phi(n)=n*(1-\frac{1}{p_{1}})*(1-\frac{1}{p_{2}})...*(1-\frac{1}{p_{k}})
phi(n)=n∗(1−p11)∗(1−p21)...∗(1−pk1)
p为n的质因子。
//计算单个值欧拉函数值
int get_phi(int n)
{
int m=sqrt(n+0.5);
int ans=n;
for(int i=2;i<=m;i++)
{
if(n%i==0)
{
ans=ans/i*(i-1);
while(n%i==0) n/=i;
}
}
if(n>1) ans=ans/n*(n-1);
return ans;
}
//利用筛法求1~n的phi值
void get_phi(int n)
{
phi[1]=1;
for(int i=2;i<=n;i++)
{
if(!phi[i])
{
for(int j=i;j<=n;j++)
{
if(!phi[j]) phi[j]=j;
phi[j]=phi[j]/i*(i-1);
}
}
}
}
4.欧拉定理:
∀
a
,
m
∈
Z
+
,
s
.
t
.
g
c
d
(
a
,
m
)
=
1
,
则
一
定
满
足
a
ϕ
(
m
)
≡
1
(
M
o
d
m
)
。
∀ a , m ∈ Z+ , s.t. gcd(a,m)=1,则一定满足 a^{ϕ(m)} ≡ 1 (Mod m) 。
∀a,m∈Z+,s.t.gcd(a,m)=1,则一定满足aϕ(m)≡1(Modm)。该定理被称作欧拉定理。由此也可得出
a
ϕ
(
m
)
−
1
a^{ϕ(m)-1}
aϕ(m)−1为a在模m意义下的逆。
扩展欧拉定理:
a
b
≡
{
a
b
%
ϕ
(
m
)
(
g
c
d
(
a
,
m
)
=
=
1
)
a
b
(
g
c
d
(
a
,
m
)
!
=
1
&
b
<
ϕ
(
m
)
)
a
b
%
ϕ
(
m
)
+
ϕ
(
m
)
(
g
c
d
(
a
,
m
)
!
=
1
&
b
≥
ϕ
(
m
)
)
(
m
o
d
m
)
a^b \equiv\begin{cases} a^{b%\phi(m)} (gcd(a,m)==1)\\ a^b (gcd(a,m) !=1 &b<\phi(m))\\ a^{b%\phi(m)+\phi(m)} (gcd(a,m)!=1&b\geq\phi(m)) \end{cases}(mod m)
ab≡⎩⎪⎨⎪⎧ab%ϕ(m) (gcd(a,m)==1)ab (gcd(a,m)!=1&b<ϕ(m))ab%ϕ(m)+ϕ(m) (gcd(a,m)!=1&b≥ϕ(m))(mod m)
证明当时看的大佬博客:链接
5.卢卡斯定理:Lucas定理用于组合数取模,如对
C
n
m
C_{n}^{m}
Cnm取模公式如下:
L
u
c
a
s
(
n
,
m
,
p
)
=
C
n
%
p
m
%
p
×
L
u
c
a
s
(
n
/
p
,
m
/
p
,
p
)
(
保
证
p
为
素
数
)
Lucas(n,m,p)=C_{n\%p}^{m\%p}×Lucas(n/p,m/p,p ) \quad (保证p为素数)
Lucas(n,m,p)=Cn%pm%p×Lucas(n/p,m/p,p)(保证p为素数)
可用于n,m较大,但模数p较小的情况。注意对于
C
n
m
C_{n}^{m}
Cnm若m>n则为0。
ll kx[maxn];//保存阶乘,若多组询问可用一个ky[]数组保存逆
ll C(ll n,ll m,ll p)
{
if(m>n) return 0;
else return kx[n]*quickpow(kx[m],p-2,p)%p*quickpow(kx[n-m],p-2,p);
}
ll lucas(int n,int m,int p)
{
if(m==0) return 1;
else
{
ll ans=lucas(n/p,m/p,p)*C(n%p,m%p,p);
return ans;
}
}
附上洛谷大佬证明:链接
扩展卢卡斯定理:待补
6,中国剩余定理:解决多个同余方程,且模数互质。这个证明看的紫书
ll c[maxn],m[maxn];
void exgcd(ll a,ll b,ll &d,ll &x,ll &y)
{
if(!b)
{
d=a,x=1,y=0;
}
else
{
exgcd(b,a%b,d,y,x);
y-=x*(a/b);
}
}
ll china(int n)
{
ll M=1,ans=0;
for(int i=1;i<=n;i++) M*=m[i];
ll x,y,d;
for(int i=1;i<=n;i++)
{
ll w=M/m[i];
exgcd(w,m[i],d,x,y);//解wx+m[i]y=1(即gcd(w,m[i]))
//显然wx%m[i]=1
ans+=w*(x%M)%M*c[i]%M;
ans=(ans%M+M)%M;
}
//最终答案ans=w1*x1*c1+w2*x2*c2...wn*xn*cn.满足所有同余方程
//比如余m[1]只有(w1x1)%m[1]=1,其他应为w中含有m1因子都为0
return ans;
}
扩展中国剩余定理:当多个同余方程模数不互质的时候可用该定理。
ll c[maxn],m[maxn];
ll gcd(ll a,ll b)
{
if(a<b) swap(a,b);
return b==0?a:gcd(b,a%b);
}
ll qmul(ll x,ll y,ll p)
{
ll ans=0;
while(y)
{
if(y&1) ans=(ans+x)%p;
x=(x<<1)%p; y>>=1;
}
return ans;
}
void exgcd(ll a,ll b,ll &d,ll &x,ll &y)
{
if(!b)
{
d=a,x=1,y=0;
}
else
{
exgcd(b,a%b,d,y,x);y-=x*(a/b);
}
}
ll exchina(int n)
{
ll x,y,d;
ll M=m[1],ans=(c[1]%m[1]+m[1])%m[1];
for(int i=2;i<=n;i++)
{
exgcd(M,m[i],d,x,y);
ll b=((c[i]-ans%m[i])%m[i]+m[i])%m[i];
/*前k-1个通解x=x'+t*M,加入第k个方程,要满足x'+t*M≡c[k](mod m[k])
相当于解该方程:M*t+m[i]*y=c[k]-x'(可调整为模m[i]意义下的正数)。*/
if(b%d!=0) return -1;
x=qmul(x,b/d,m[i]);
ans+=x*M;//x就是t,相当于满足前k-1个方程的通解公式,同时也是第k个方程的解。
M*=m[i]/d;
ans=(ans%M+M)%M;
}
return ans;
}
证明附上链接:链接
7BSGS算法:又称大步小步算法
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<set>
#include<queue>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<stack>
#include<map>
using namespace std;
typedef long long ll;
const int maxn=1e5+7;
ll a,b,p;
map<ll,int> op;
ll qmul(ll x,ll y,ll p)
{
ll ans=0;
while(y)
{
if(y&1)
{
ans=(ans+x)%p;
}
x<<=1;x%=p;
y>>=1;
}
return ans;
}
ll quickpow(ll x,ll y,ll p)
{
ll ans=1;
while(y)
{
if(y&1)
{
ans=ans*x%p;
}
x=x*x%p;
y>>=1;
}
return ans;
}
ll log_mod(ll a,ll b,ll p)
{
int m=sqrt(p+0.5);
ll v=quickpow(a,m,p);
v=quickpow(v,p-2,p);
ll e=1;op[1]=0;
for(int i=1;i<m;i++)
{
e=qmul(e,a,p);
if(!op.count(e)) op[e]=i;
}
for(int i=0;i<m;i++)
{
if(op.count(b%p))
return i*m+op[b];
b=b*v%p;
}
return -1;
}
int main()
{
scanf("%lld%lld%lld",&p,&a,&b);
ll ans=log_mod(a,b,p);
if(ans==-1) printf("no solution\n");
else printf("%lld\n",ans);
return 0;
}
9莫比乌斯反演
F
(
n
)
和
f
(
n
)
为
定
义
在
非
负
整
数
上
的
两
个
函
数
F(n)和f(n)为定义在非负整数上的两个函数
F(n)和f(n)为定义在非负整数上的两个函数
若有
F
(
n
)
=
∑
d
∣
n
f
(
d
)
F(n)=\sum_{d|n}f(d)
F(n)=∑d∣nf(d)
则
f
(
n
)
=
∑
d
∣
n
μ
(
d
)
F
(
⌊
n
d
⌋
)
f(n)=\sum_{d|n}\mu(d)F(\lfloor\frac{n}{d}\rfloor)
f(n)=∑d∣nμ(d)F(⌊dn⌋)
莫比乌斯函数性质:
1,对于任意正整数n,
∑
d
∣
n
μ
(
d
)
=
[
n
=
1
]
\sum_{d|n}\mu(d)=[n=1]
∑d∣nμ(d)=[n=1]([n=1]表示只有当n=1成立时,返回值为1;否则,值为0;
2,对于任意正整数n,
∑
d
∣
n
μ
(
d
)
d
=
ϕ
(
n
)
n
\sum_{d|n}\frac{\mu(d)}{d}=\frac{\phi(n)}{n}
∑d∣ndμ(d)=nϕ(n)