Part 1【同余相关、phi&u】
答案是会什么,什么都不会。
1.Exgcd
裴蜀定理:
有解当且仅当 。整数条件下。
推广:
对于任意
。当 有解。应用见 CF19xxD。
现在我们要得到
考虑 gcd 的辗转相除法:
所以我们有:
注意,这里
所以
那么递归求解,取
边界?普通 gcd 可知
void exgcd(int a, int b, int &x, int &y) {
if(!b) return x = 1, y = 0, void();
exgcd(b, a % b, y, x), y -= a / b * x;
}
1.1 通解
直接给出结论:设
可以根据这个求范围内的最大最小值,解的个数等信息……
并且该算法有一个性质就是你求得的
1.2 应用
- 转化方程
为二元一次方程求解,比如求逆元。也可以根据这个知道使用条件是 。
1.3 例题
先鸽。
2. BSGS
求解方程
2.1 特殊情况
一个很重要的前提:
设
取
那就简单了,预处理出左边,枚举右边即可,由于可能要用 map,所以复杂度根号对数。
2.2 ExBSGS
注意上面的算法有一个前提:
why?因为你把
那干脆就强制改成互质。每次对一个
你把
注意到
注意取模,特判
时间复杂度
int qkpow(int a, int b, int Mod) {
if(!b) return 1;
if(b & 1) return a * qkpow(a, b - 1, Mod) % Mod;
int t = qkpow(a, b >> 1, Mod); return t * t % Mod;
}
void exgcd(int a, int b, int &x, int &y) {
if(!b) return x = 1, y = 0, void();
exgcd(b, a % b, y, x), y -= a / b * x;
}
int inv(int x, int p) { int sb; exgcd(x, p, sb, *new int); return (sb % p + p) % p; }
map <int, int> mp;
int BSGS(int a, int b, int p) {
int A = 1, B = sqrt(p) + 1; mp.clear();
for(int i = 1; i <= B; i++) mp[(A = A * a % p) * b % p] = i;
for(int i = 1, AA = A; i <= B; i++, AA = AA * A % p)
if(mp[AA]) return i * B - mp[AA];
return -1;
}
void ExBSGS(int a, int b, int p) { // 最终要使得 a, p 互质
int s = 0; a %= p, b %= p;
while(__gcd(a, p) != 1) {
if(b == 1) return printf("%lld\n", s), void();
int D = __gcd(a, p);
if(b % D) return puts("No Solution"), void();
b /= D, p /= D; b = b * inv(a / D, p) % p;
++s; a %= p;
}
int ans = BSGS(a, b, p);
if(ans == -1) puts("No Solution");
else printf("%lld\n", ans + s);
}
3. CRT
中国剩余定理。中国真是太厉害啦。
3.1 互质情况
即,
勾石。
设
给出构造:
发现不够,还需要一个
最后
3.2 ExCRT
任意
核心思想是每次只合并 2 个方程。
首先对于
那么就有
又一个问题,
所以新方程:
加入一个方程合并一次到最后就好了。
cin >> n >> b1 >> a1; bool flag = 1;
for(int i = 2, a2, b2;i <= n; ++i) {
b2 = read(), a2 = read(); if(!flag) continue ;
if((a2 - a1) % __gcd(b1, b2)) { flag = 0; continue ; }
int GCD = __gcd(b1, b2); int k = ((a2 - a1) % b2 + b2) % b2 / GCD;
int x; exgcd(b1 / GCD, b2 /= GCD, x, *new int); x = (x % b2 + b2) % b2;
x = (__int128)x * k % b2;
a1 += x * b1, b1 *= b2, a1 = (a1 % b1 + b1) % b1;
}
注意上面代码中
难绷。
3.3 例题
古代猪文
用费马小定理的话,发现模数是个偶数,搞不了。
所以把这个模数拆成多个质因子,每个单独求答案,最后 CRT 还原出来即可。
屠龙勇士
几乎板子?
预处理一下,然后就是多个 exgcd 的方程,变一下就是 excrt 了。记得和某个值取 max。
4.欧拉函数
4.1 定义
4.2 性质
4.2.1 性质一
若
为质数,则 。
4.2.2 性质二
若
为质数,则 。
考虑
4.2.3 性质三
若
,则 。
4.2.4 性质四
若
,则 。
3 和 4 可以感性理解。或者直接用 4.2.5 即可。
4.2.5 性质五
设
的唯一分解为: ,则 。
反复用上面的性质证就可以了。
根据这个,可以根号地求出单个欧拉值。
4.2.6 性质六
。
考虑
4.2.7 性质七 欧拉反演
。
首先
根据性质六:
4.2.8 性质八
对于
, 。
知道
4.2.9 性质九
若
,则 。
因为
4.3 线性筛欧拉函数
根据性质 3、4,再结合线性筛即可。
void init(int len) {
phi[1] = f[1] = 1;
for(int i = 2;i <= len; ++i) {
if(!f[i]) p[++cnt] = i, phi[i] = i - 1;
for(int j = 1;p[j] * i <= len and j <= cnt; ++j) {
f[p[j] * i] = 1; phi[i * p[j]] = phi[i] * (p[j] - 1);
if(i % p[j] == 0)
{ phi[i * p[j]] = p[j] * phi[i]; break; }
}
}
}
4.4 欧拉定理
5. 莫比乌斯函数
本身也没什么好讲的,主要是狄利克雷卷积那一部分。
5.1 性质
5.1.1
,即 。非常重要。
考虑证明:
将
的所有 的质因子去掉,得到 。可知
设,故 。
当时特殊考虑,为 ;其余恒为 。
由此我们看出
所以我们引出反演:
5.1.2
- 若
,则 。
根据欧拉反演:
5.1.3
5.1.4
求
引理:
证明考虑钦定选
然后就是一些应用。
6. ex:线性筛求积性函数(一般)
因为自己唐完了。
记录
当然,最开始
然后可以根据积性函数性质更新了:
若
注意一点,若
Hint
对于一般情况,积性函数一定可以用线性筛。但是,部分普通函数也可以用线性筛。如:P2257。
在时间不卡的情况下,可以用埃氏筛轻松地求解任意函数,时间为
SP5971
注意积性函数性质:若
我们要求
这里
注意上文有一个式子:
后面那一坨要记得加上,然后
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端