数学
预计是遇到各种零散的东西就把它们记下来,记得足够多的时候整理一下。
参考自各种奇奇怪怪的博客知乎 B 站和机房大佬。
因为博主显然对这些东西的理解也并不算深刻,看着玩吧。有机会就优化一下。
参考资料:
数论类
费马小定理
, 为质数。
待填。
应用
求逆元
即
裴蜀定理
- 二元一次不定方程
有整数解仅当 。
扩展欧几里得算法(exgcd)
可以在用欧几里得算法求 gcd 的时候顺便解出
流程
其实挺妙的。本质上是通过反复递归构造同样形式的问题直到变成一个相当简单的方程,直接求解后一层层带回去。
由欧几里得算法得
回带的时候考虑
博主为了压代码长度放弃了求 gcd 的功能。
void ecd(ll a,ll b,ll &x,ll &y) { b?(ecd(b,a%b,y,x),y-=a/b*x):(x=1,y=0); }
这样求完之后
解的范围
总之以后用 exgcd 的时候大概率就不需要担心爆 int/long long 的问题了。
应用
求逆元
有费马了还要 exgcd 干嘛啊。
模数不是质数的时候你就寄喽。
若我们要求
很显然在
求解二元一次不定方程
你需要求
所以我们把
不过通常问题不会这么简单,题目大概率对求出的解有限制,比如要求
令
然后针对题目限制去同时变化
线性同余方程组问题
中国剩余定理(CRT)
考虑对于每个方程构造一个
首先如果要在其他方程的模意义下为
然后看怎么让
只要没有模数同时对应两个不同余数就有解。
ll crt(ll n,ll *m,ll *a) {
ll mul=1; __int128 res=0;
for (ll i=1;i<=n;i++) mul*=m[i];
for (ll i=1,x;i<=n;i++) ecd(mul/m[i],m[i],x,*new ll),res+=(__int128)a[i]*(mul/m[i])*(x+mul);
return res%mul;
}
扩展中国剩余定理(exCRT)
这个不需要
假设有两个方程
有
复杂度也是
ll excrt(ll n,ll *m,ll *a) {
for (ll i=2;i<=n;i++) {
ll g=__gcd(m[i],m[1]),f=a[i]-a[1],p,q;
if (f%g!=0) return -1;
m[i]/=g,ecd(m[1]/g,m[i],p,q);
a[1]+=(__int128)f/g*p%m[i]*m[1],m[1]*=m[i],a[1]%=m[1];
}
return (a[1]%m[1]+m[1])%m[1];
}
数论分块
求解类似
如果是
以两个参数
for (int l=1,r;l<=min(n,m);l=r+1) {
r=min(n/(n/l),m/(m/l));
sum+=(r-l+1)*f(n/l);
}
欧拉函数(φ)
为 中与 互质的数的个数。
性质
是积性函数。即当 互质时, 。 为质数时, 。- 计算式:设
被唯一分解为 ,则 。 - 线性筛:
其实基本所有满足积性函数的数论函数都可以线性筛。
struct mth {
int vis[N],prm[N],cnn;
int phi[N];
mth() {
vis[0]=vis[1]=1,phi[1]=1;
for (ll i=2;i<N;i++) {
if (!vis[i]) prm[++cnn]=i,phi[i]=i-1;
for (ll j=1;j<=cnn&&i*prm[j]<N;j++) {
vis[i*prm[j]]=1;
if (i%prm[j]==0) { phi[i*prm[j]]=phi[i]*prm[j]; break;}
phi[i*prm[j]]=phi[i]*phi[prm[j]];
}
}
}
} V;
。
欧拉定理
- 当
与 互质时, 。
在
扩展欧拉定理
用于解决
应用:欧拉降幂
众所周知指数不能直接取模。那么用扩展欧拉定理就能知道指数要模什么了。前提是你知道指数和
莫比乌斯函数(μ)
若
莫比乌斯反演
若有函数
还有一种也比较常用(?)的形式
性质
。
可用于将某些
。
由之前结论
,反演得 ,整理一下。
离散对数问题
可以发现这玩意你不太好直接算出来。
大步小步算法(BSGS)
当 北上广深 BSGS。
一个个枚举
考虑令
显然
有些阴间情况要特判。
ll bgs(ll a,ll b,ll P) {
a%=P,b%=P;
if (a==0&&b!=0) return -J;
if (P==1||b==1) return 0;
ll c=sqrt(P)+1,x=1,y=1; unordered_map<ll,ll> mp;
for (ll i=0;i<c;i++) mp[x*b%P]=i,(x*=a)%=P;
for (ll i=1;i<=c;i++) if (mp.count((y*=x)%=P)) return i*c-mp[y];
return -J;
}
扩展大步小步算法(exBSGS)
所以这时我们考虑把
令
这时可能
直到最后得到
ll egs(ll a,ll b,ll P) {
a%=P,b%=P;
ll res=0;
for (ll d;(d=__gcd(a,P))!=1;res++) {
if (b==1) return res;
if (b%d) return -J;
P/=d,b=b/d*inv(a/d,P)%P,a%=P;
}
return bgs(a,b,P)+res;
}
质因数分解
费马素性测试
Miller-Rabin 素性测试
Pollard-Rho
组合类
定义
博主倾向于写
计算
使用定义
一般没有模数要写高精而且
递推式
没有模数时这样可以不用写乘 & 除。
普遍求法
对大质数模数
卢卡斯定理(Lucas)
然而当模数
人话就是把商和余数分离出来是没有影响的。证明等博主会了再说。
右边那项的
预处理
CRT 套卢卡斯定理
把模数分解为一堆小质数,分别用卢卡斯定理求出组合数模这些小质数时得到的答案,再 CRT 把这堆玩意合起来。复杂度是
扩展卢卡斯定理(exLucas)
还有一种更为直接的任意模数求组合数:当卢卡斯定理里的
性质
- 范德蒙德卷积:
博弈类
Nim 游戏
堆石子,两个人轮流取,每次可以取走一堆石子里的若干个。但不能不取,没得取的输,问先手后手谁有必胜策略。
直接摆结论。设
简单理解:因为异或运算的奇妙性质,只要某一刻
,此时操作的人必有一种方法使得下一步 ,而显然如果这一刻 ,操作完必定 。已知最后石子一定被取完,正好有 ,所以只要先手拿到的状态是 ,他就必定有方法反复让 的结果反复横跳,把后手干碎。反之他自己就会被后手干碎。这种必胜条件的推导可以参考一下。
SG 函数
- 有一张无环的有向图,上面有若干个棋子(可以有多个棋子在同一点上),两个人轮流操作,每次可以将一个棋子往它所在的点的一条出边移动一步,动不了的输,问先手后手谁有必胜策略。
先考虑只有一个棋子的情况。
定义一个博弈状态的 SG 函数
因为 mex 有性质:一个点
SG 函数的逆天之处在于它能在多个棋子的时候也能用。也就是如果一个博弈问题可以拆成若干个博弈子问题(子问题全部终止时大问题才终止,每次操作只能影响一个子问题),那么大问题的 SG 就是小问题的 SG 异或和。在这个问题里先手必胜仅当每个棋子单独的
多项式
期望概率类
概率
期望
期望可以理解为所有可能出现的情况的答案取个平均值。
形式化的就是
性质
- 线性性:通俗来说就是和的期望等于期望的和(
)。这个好像有些时候不成立,但是博主暂未理解,待补。
应用:
- 求一个骰子投两遍朝上那面的点数之和的期望。
设第一次和为
有
个糖,每个糖有一个种类 。对于每一个 问:你会从中随机选 颗糖吃掉,问吃掉的糖的不同种类数的期望。
, ,4s,1GB。
根据线性性,期望可以拆成每种糖选的概率加起来(因为拆完之后
设种类
现在是
- 只算输入过的
。变 。 - 将相同的
放在一起统一计算。因为 ,不同的 最多有 个。变 。可以过了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】