Part 1【同余相关、phi&u】

答案是会什么,什么都不会。

1.Exgcd

裴蜀定理:ax+by=c 有解当且仅当 c=k×(a,b)。整数条件下。

推广:

对于任意 x1,x2,...,xm。当 (a1,a2,...,am)|c 有解。应用见 CF19xxD。

现在我们要得到 ax+by=c 的一个解。不妨先解 c=(a,b),再乘一个系数。

考虑 gcd 的辗转相除法:(a,b)=(b,amodb)

所以我们有:ax+by=(a,b),bx+(amodb)y=(b,amodb)

注意,这里 x,y 是根据 (b,amodb) 得到的,我们需要还原使得 x,y 对应 (a,b)

所以 ax+by=bx+(amodb)y=ay+b(xaby)

那么递归求解,取 x=y,y=xaby 即可。

边界?普通 gcd 可知 b0=0,a0=(a,b),此时取 x0=1,y0=0 即满足。(此时 b 直接是 0 了,所以变成了 1 元方程)

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 通解

直接给出结论:设 d=(a,b)

x=x0+bdk, y=y0adk

可以根据这个求范围内的最大最小值,解的个数等信息……

并且该算法有一个性质就是你求得的 x,y 满足在所有解中 |x|+|y| 最小。

1.2 应用

  1. 转化方程 axb(modp) 为二元一次方程求解,比如求逆元。也可以根据这个知道使用条件是 ap

1.3 例题

先鸽。

2. BSGS

求解方程

axb(modp)

2.1 特殊情况

一个很重要的前提:x 一定在 [0,p) 有解。

x=AMB(B[0,M)),类似除和模。变形:aAMbaB(modp)

M=p。那么右边就只有根号种取值,左边也只有根号种取值。

那就简单了,预处理出左边,枚举右边即可,由于可能要用 map,所以复杂度根号对数。

2.2 ExBSGS

注意上面的算法有一个前提:ap

why?因为你把 aB 移过去需要这个前提,否则显然不成立。

那干脆就强制改成互质。每次对一个 ap 除以 gcd D

aDax1bD(modpD)

你把 a/D 移过去,因为和 p/D 互质所以可以用 exgcd 求逆元。

注意到 ap/gcd(a,p) 不一定互质,所以要一直循环下去做,直到 ap

注意取模,特判 b=1 返回 0

时间复杂度 O(p+log2p)。代码中 BSGS 返回了最小的 x

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 互质情况

即,ij,mimj

勾石。

X=a×c,考虑方程 iX=jiajcj+aici,要求前面一坨无关,即是 mi 的倍数。而 ci 却不能是 mi 的倍数。

给出构造:ci=Mmi,其中 M=mi

发现不够,还需要一个 di,因为每个方程要有:aicidiai(modmi),那么自然就有 dicimi 的逆元。因为 mi 不一定质数,而 cimi 互质。

最后 x=aicidi

3.2 ExCRT

任意 mi

核心思想是每次只合并 2 个方程。

首先对于 xa1(modm1),有 x=k1m1+a1;代入第二个方程:k1m1+a1=k2m2+a2

那么就有 k1m1k2m2=a2a1,exgcd 求即可。

又一个问题,xa1(modm1),xa2(modm2) 合并后,m 怎么变?结论:lcm(m1,m2)

所以新方程:xk1m1+a1(modlcm(m1,m2))。后面是个常数。

加入一个方程合并一次到最后就好了。

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;
}

注意上面代码中 b 代表 m

难绷。

3.3 例题

古代猪文

用费马小定理的话,发现模数是个偶数,搞不了。

所以把这个模数拆成多个质因子,每个单独求答案,最后 CRT 还原出来即可。

屠龙勇士

几乎板子?

预处理一下,然后就是多个 exgcd 的方程,变一下就是 excrt 了。记得和某个值取 max。

4.欧拉函数

4.1 定义

φ(n) 定义为 [1,n] 中于 n 互质的数。

4.2 性质

4.2.1 性质一

p 为质数,则 φ(p)=p1

4.2.2 性质二

p 为质数,则 φ(pk)=(p1)pk1

考虑 [1,pk] 中有多少个是 p 的倍数,减去即可,共 pk1 个。

4.2.3 性质三

a b,则 φ(ab)=φ(a)×φ(b)

4.2.4 性质四

ab,则 φ(ab)=a×φ(b)

3 和 4 可以感性理解。或者直接用 4.2.5 即可。

4.2.5 性质五

n 的唯一分解为:n=i=1kpici,则 φ(n)=n×i=1kpi1pi

反复用上面的性质证就可以了。

根据这个,可以根号地求出单个欧拉值。

4.2.6 性质六

φ(nd)=i=1n[gcd(i,n)=d]

考虑 gcd(i,n)=d 的一个必要条件是 id nd。现在给定 n,d,那么 i 的个数就是满足 id nd 的个数,即 φ(nd)

4.2.7 性质七 欧拉反演

dnφ(d)=n

首先 n=dni=1n[(i,n)=d]

根据性质六:n=dnφ(nd)=dnφ(d)

4.2.8 性质八

对于 n>22φ(n)

知道 xn,则 nxn 即可。

4.2.9 性质九

ab,则 φ(a)φ(b)

因为 b 包含了 a 的质因子,所以 p 那一坨的式子也满足整除关系。

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

  • μ1=ε,即 dnμ(d)=[n=1]非常重要。

考虑证明:

n 的所有 ci2 的质因子去掉,得到 n。可知 μ(n)=μ(n)
n=i=1kpi,故 μ(n)=i=0k(ki)(1)i=(11)k
k=0 时特殊考虑,为 1;其余恒为 0

由此我们看出 μ 大致就是 11

所以我们引出反演:

5.1.2

  • g=f1,则 f=gμ

根据欧拉反演:id=φ1。可知:φ=idμ,即:

φ(n)=dnμ(d)nd

5.1.3

i=1nj=1m[gcd(i,j)=1]

=i=1nj=1mdnμ(d)

=d=1min(n,m)μ(d)i=1nj=1m[didj]

=d=1min(n,m)μ(d)ndmd

5.1.4

i=1ni=1md(i×j)

引理:d(i×j)=xiyj[gcd(x,y)=1]

证明考虑钦定选 y 的前提要选完 x 中所有 y 里面的质因子。而选 x 中的质因子则一定不能选 y,这样就一一对应。

然后就是一些应用。

6. ex:线性筛求积性函数(一般)

因为自己唐完了。

记录 g(n)=p1c1,其中 p1n 最小的质因子。(为什么记录 p1?因为最先筛到,就这样)

当然,最开始 g(n) 最开始肯定 c1 不对,需要动态更新。

然后可以根据积性函数性质更新了:

n=g(n),则 O(1) 直接计算即可;否则 f(n)=f(g(n))×f(ng(n))

注意一点,若 (x,y)1 则不能直接积。

Hint

对于一般情况,积性函数一定可以用线性筛。但是,部分普通函数也可以用线性筛。如:P2257

在时间不卡的情况下,可以用埃氏筛轻松地求解任意函数,时间为 O(nloglogn)

SP5971

注意积性函数性质:若 f 为积,则 f1 也为积。

我们要求 g=f1,即 g(n)=dnf(d),那么 g 也满足积性函数性质。

这里 f(n)=nφ(n),显然是积。

注意上文有一个式子:

=12n(φ(n)+[n=1])

后面那一坨要记得加上,然后 g(n) 计算时注意 d=1

posted @   LCat90  阅读(15)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示