数论初步总结

UPD:类欧更新啦!

按照课件的知识点总结吧

数论一大堆公式打的我烦

众所周知,取模运算对于加法,减法,乘法都试用

( a % p + b % p ) % p = ( a + b ) % p (a\%p+b\%p)\%p=(a+b)\%p (a%p+b%p)%p=(a+b)%p

( a % p − b % p ) % p = ( a − b ) % p (a\%p-b\%p)\%p=(a-b)\%p (a%pb%p)%p=(ab)%p

( a % p ∗ b % p ) % p = ( a ∗ b ) % p (a\%p*b\%p)\%p=(a*b)\%p (a%pb%p)%p=(ab)%p

加法证明直接带余除法分解一下就行了,其他类似

为减少模的常数,通常试用减法法加速

快速幂:把指数按二进制展开,然后累乘就OK
int pw(int a, int b) {
	int res = 1 ;
	rep(; b; b >>= 1, a = 1ll * a * a % p) if (b & 1) res = 1ll * res * a % p ; 
	return res ;
}
快速乘,也是同理,就是解决那些爆ll的乘法运算,也是按位展开做加法
int mul(int a, int b) {
	int res = 0 ;
	for(; b; b >>= 1, a = (ll)(a + a) % p) if (b & 1) res = (ll)(res + a) % p ;
	return res ;
}

之后一个题目:HDU 5187

可以分类讨论:

  1. 对于整段序列单调增或减,就 2 2 2种情况。
  2. 对于先增后减或先减后增:确定一个序列中的最小值(最大值),其他的要么在左边,要么在右边,有 2 ∗ 2 n − 1 2*2^{n-1} 22n1种,而在这 2 n 2^n 2n种情况中重复计算了单调增或减的情况 2 2 2

所以答案就是 2 n − 2 2^n-2 2n2,用快速乘和快速幂解决

之后是整除性和约数

如果 a a a b b b的约数,则 a ∣ b a|b ab

之后一些显然的性质:

  1. a ∣ b , b ∣ c a|b,b|c ab,bc,则 a ∣ c a|c ac
  2. a ∣ b , c ∣ d a|b,c|d ab,cd,则 a c ∣ b d ac|bd acbd
  3. a ∣ b a|b ab a ∣ c a|c ac,则 a ∣ ( n b + m c ) a|(nb+mc) a(nb+mc)
  4. m a ∣ m b ma|mb mamb,则 a ∣ b a|b ab

算术基本定理:每个大于 1 的正整数都可以被唯一地写成若干素数的乘积(不考虑负数)

我们把一个数写成质数相乘的形式的式子称为质因子分解式

n = ∏ a i p i n=\prod_{}{a_i}^{p_i} n=aipi,则其约数个数 d ( n ) d(n) d(n) ∏ p i + 1 \prod_{}{p_i+1} pi+1

素数理论:

素数是大于 1 的正整数,且除了 1 和它自身不能被其他正整数整除

素数无限定理:存在无穷多个素数,用反证法证明

线性筛素数:只让每个合数被它的最小质因子筛去,复杂度是 O ( n ) O(n) O(n)

void select(int n) {
	for (int i = 2; i <= n; i++) f[i] = 1 ;
	f[0] = f[1] = 0 ;
	tot  = 0 ;
	for (int i = 2; i <= n; i++) {
		if (!f[i]) continue ;
		prime[++tot] = i ;
		for (int j = 1; j <= tot && prime[j] * i <= n; j++) {
			if (i * prime[j] > n) break ;
			f[i * prime[j]] = 0 ;
			if (i % prime[j] == 0) break ; //保证只被最小的质因数筛到
		}
	}
}

素数分布:

设函数 π ( x ) \pi(x) π(x)表示不超过正实数 x x x的素数个数

lim ⁡ n → ∞ π ( x ) x log ⁡ x = 1 \lim\limits_{n\to\infty}\frac{\pi(x)}{\frac{x}{\log_x}}=1 nlimlogxxπ(x)=1,也就是 π ( x ) ≈ x log ⁡ x \pi(x)≈\frac{x}{\log_x} π(x)logxx

所以我们开数组时空间除以10就好了

同余定理

定理: gcd ⁡ ( a , b ) = gcd ⁡ ( b , a % b ) \gcd(a,b)=\gcd(b,a\%b) gcd(a,b)=gcd(b,a%b)

证明:设 a = k b + r a=kb+r a=kb+r,则 r = a % b r=a\%b r=a%b

假设 d d d gcd ⁡ ( a , b ) \gcd(a,b) gcd(a,b),则 d ∣ a , d ∣ b d|a,d|b da,db

r = a − k b ​ r=a-kb​ r=akb,因此 d ∣ r ​ d|r​ dr,因此d也是 gcd ⁡ ( b , a % b ) ​ \gcd(b,a\%b)​ gcd(b,a%b)

假设 d d d gcd ⁡ ( b , a % b ) \gcd(b,a\%b) gcd(b,a%b),则 d ∣ b , d ∣ r d|b,d|r db,dr

a = k b + r a=kb+r a=kb+r,因此 d ∣ a d|a da,因此 d d d也是 gcd ⁡ ( a , b ) \gcd(a,b) gcd(a,b)

因此 ( a , b ) (a,b) (a,b) ( b , a % b ) (b,a\%b) (b,a%b)的公约数相同,则其最大公约数也必定相同

int gcd(int a, int b){
	return !b : a ? gcd(b, a % b) ;
}

更相减损术

一种计算 g c d ( a , b ) gcd(a,b) gcd(a,b)的方法

a &gt; b a&gt;b a>b,交换 a , b a,b a,b

a a a b b b偶则 gcd ⁡ ( a , b ) = gcd ⁡ ( a , b / 2 ) \gcd(a,b)=\gcd(a,b/2) gcd(a,b)=gcd(a,b/2)

a a a b b b奇则 gcd ⁡ ( a , b ) = gcd ⁡ ( a / 2 , b ) \gcd(a,b)=\gcd(a/2,b) gcd(a,b)=gcd(a/2,b)

a a a b b b偶则 gcd ⁡ ( a , b ) = 2 ∗ gcd ⁡ ( a / 2 , b / 2 ) \gcd(a,b)=2*\gcd(a/2,b/2) gcd(a,b)=2gcd(a/2,b/2)

a a a b b b奇则 gcd ⁡ ( a , b ) = gcd ⁡ ( a − b , b ) \gcd(a,b)=\gcd(a-b,b) gcd(a,b)=gcd(ab,b)

以上两种算gcd的方法都是 O ( l o g n ) O(logn) O(logn)

万恶的SD省选出了一道 毒瘤题 SuperGCD,就是a,b很大( 1 0 10000 10^{10000} 1010000),求GCD

用上面的方法,高精需要支持判0,除2,乘2,减

代码有毒就不发了

丢番图方程( a x + b y = c ax+by=c ax+by=c

裴蜀定理: a x + b y = c ax+by=c ax+by=c有解当且仅当 gcd ⁡ ( a , b ) ∣ c \gcd(a,b)|c gcd(a,b)c

扩展欧几里得算法:求ax+by=c的自然数解

推导:

设方程

{ a x 1 + b y 1 = gcd ⁡ ( a , b ) b x 2 + ( a % b ) y 2 = g c d ( b , a % b ) \begin{cases} ax_1+by_1=\gcd(a,b) \\ bx_2+(a\%b)y_2=gcd(b,a\%b) \end{cases} {ax1+by1=gcd(a,b)bx2+(a%b)y2=gcd(b,a%b)

gcd ⁡ ( a , b ) = gcd ⁡ ( b , a % b ) \gcd(a,b)=\gcd(b,a\%b) gcd(a,b)=gcd(b,a%b)继续推:

a x 1 + b y 1 = b x 2 + ( a % b ) y 2 = b x 2 + ( a − ⌊ a b ⌋ ∗ b ) y 2 = a y 2 + b ( x 2 − ⌊ a b ⌋ ∗ y 2 ) ax_1+by_1=bx_2+(a\%b)y_2=bx_2+(a-\left\lfloor{\frac{a}{b}}\right\rfloor*b)y_2=ay_2+b(x_2-\left\lfloor{\frac{a}{b}}\right\rfloor*y_2) ax1+by1=bx2+(a%b)y2=bx2+(abab)y2=ay2+b(x2bay2)

所以我们得到

{ x 1 = y 2 y 1 = x 2 − ⌊ a b ⌋ ∗ y 2 \begin{cases} x_1=y_2 \\ y_1=x_2-\left\lfloor{\frac{a}{b}}\right\rfloor*y_2 \end{cases} {x1=y2y1=x2bay2

很显然, b = 0 , a = gcd ⁡ ( a , b ) b=0,a=\gcd(a,b) b=0,a=gcd(a,b)时, gcd ⁡ ( a , b ) x = gcd ⁡ ( a , b ) \gcd(a,b)x=\gcd(a,b) gcd(a,b)x=gcd(a,b),所以 x = 1 x=1 x=1

于是我们先从原方程递归到b=0,然后从末状态向上回溯,就能够得到方程的一组解

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

a x + b y = c ax+by=c ax+by=c的通解

( x 1 , y 1 ) (x_1,y_1) (x1,y1)为方程 a x + b y = c ax+by=c ax+by=c的一组解

( x 1 + k b gcd ⁡ ( a , b ) , y 1 − k a gcd ⁡ ( a , b ) ) (x_1+\frac{kb}{\gcd(a,b)} ,y_1-\frac{ka}{\gcd(a,b)}) (x1+gcd(a,b)kb,y1gcd(a,b)ka)为方程的通解,其中 k k k为参数

代入方程易知正确性

给一例题 [NOI2002]荒岛野人

将题意转化,我们能够发现其实就是求出最小的 M M M,使得对于任意 i , j i,j i,j

C i + P i ∗ x ≡ C j + P j ∗ x ( m o d   M ) C_i+P_i*x≡C_j+P_j*x(mod \ M) Ci+PixCj+Pjx(mod M)的最小正整数解 x x x要么不存在,要么 &lt; m i n ( L i , L j ) &lt;min(L_i,L_j) <min(Li,Lj)

发现M不满足单调性,只能枚举M

将上述同余方程式变形,的到 ( P i − P j ) ∗ x − M ∗ y = C j − C i (P_i-P_j)*x-M*y=C_j-C_i (PiPj)xMy=CjCi

用扩展欧几里得去做一下就行了

int n, mx ;
int c[N], p[N], l[N] ;

int gcd(int a, int b) {
	return !b ? a : gcd(b, a % b) ;
}

int exgcd(int a, int b, int &x, int &y) {
	if (!b) {
		x = 1, y = 0 ;
		return a ;
	}
	int d = exgcd(b, a % b, y, x) ;
	y -= (a / b) * x ;
	return d ;
}

bool check(int m) {
	rep(i, 1, n)
	rep(j, i + 1, n) {
		int a = p[j] - p[i], b = m, C = c[i] - c[j], x, y, g = gcd(a, b) ;
		if (C % g == 0) {
			a /= g ;
			b /= g ;
			C /= g ;
			exgcd(a, b, x, y) ;
			b = abs(b) ;
			x = ((x * C) % b + b) % b ;
			if (!x) x += b ;
			if (x <= min(l[i], l[j])) return 0 ;
		}
	}
	return 1 ;
}

signed main(){
    scanf("%d", &n) ;
    rep(i, 1, n) scanf("%d%d%d", &c[i], &p[i], &l[i]), mx = max(mx, c[i]) ;
	// 初始洞穴,每年跳多少,寿命
	int i = mx ;
	while (1) {
		if (check(i)) print(i) ;
		i++ ;
	}
	return 0 ;
}
之后就是恶心的类欧了

首先,有一些下取整的结论:

结论1: ⌊   A + B ⌋ = A + ⌊   B ⌋ \left\lfloor\ A+B \right\rfloor=A+\left\lfloor\ B\right\rfloor  A+B=A+ B, A ∈ N A∈\N AN B ∈ R B∈\R BR

结论2:当 x ≥ y x≥y xy 时,设 x = k y + r x=ky+r x=ky+r,根据结论1易知 ⌊   A x y ⌋ = ⌊   A ( k y + r ) y ⌋ = A k + ⌊   A r y ⌋ = A ∗ ⌊   x y ⌋ + ⌊   A ( x % y ) y ⌋ \left\lfloor\ \frac{Ax}{y}\right\rfloor=\left\lfloor\ \frac{A(ky+r)}{y}\right\rfloor=Ak+\left\lfloor\ \frac{Ar}{y}\right\rfloor=A*\left\lfloor\ \frac{x}{y}\right\rfloor+\left\lfloor\ \frac{A(x\%y)}{y}\right\rfloor  yAx= yA(ky+r)=Ak+ yAr=A yx+ yA(x%y)

然后之后我们来说说类欧几里得算法

问题是求下面的三个式子:

φ ( a , b , c , n ) = ∑ i = 0 n ⌊   a i + b c ⌋ \varphi(a,b,c,n)=\sum\limits_{i=0}^n\left\lfloor\ \frac{ai+b}{c} \right\rfloor φ(a,b,c,n)=i=0n cai+b

ψ ( a , b , c , n ) = ∑ i = 0 n ⌊   a i + b c ⌋ 2 \psi(a,b,c,n)=\sum\limits_{i=0}^n\left\lfloor\ \frac{ai+b}{c} \right\rfloor^2 ψ(a,b,c,n)=i=0n cai+b2

ϕ ( a , b , c , n ) = ∑ i = 0 n i ⌊   a i + b c ⌋ \phi(a,b,c,n)=\sum\limits_{i=0}^ni\left\lfloor\ \frac{ai+b}{c} \right\rfloor ϕ(a,b,c,n)=i=0ni cai+b

n ≤ 1 0 9 n≤10^9 n109

很显然 φ \varphi φ最简单,我们先试着处理它

暴力肯定不成,数据范围提示我们要写一种 O ( l o g n ) O(logn) O(logn)的方法

ξ ( i ) = ⌊   a i + b c ⌋ \xi(i)=\left\lfloor\ \frac{ai+b}{c} \right\rfloor ξ(i)= cai+b,观察当i增大时, ξ ( i ) \xi(i) ξ(i)是怎么变的

a ≥ c a≥c ac,则 a ( i + 1 ) c = a i c + a c ≥ a i c + 1 \frac{a(i+1)}{c}=\frac{ai}{c}+\frac{a}{c}≥\frac{ai}{c}+1 ca(i+1)=cai+cacai+1

同理若 b ≥ c b≥c bc,显然 b c ≥ 1 \frac{b}{c}≥1 cb1

套着下取整符号很烦,我们试图把他拆掉

根据前面提到的结论2,我们能够将 ξ \xi ξ 变形:

ξ ( i ) = ⌊   a i + b c ⌋ = ⌊   ( a % c ) i + ( b % c ) c ⌋ + i ⌊   a c ⌋ + ⌊   b c ⌋ \xi(i)=\left\lfloor\ \frac{ai+b}{c} \right\rfloor=\left\lfloor\ \frac{(a\%c)i+(b\%c)}{c}\right\rfloor+i\left\lfloor\ \frac{a}{c} \right\rfloor+\left\lfloor\ \frac{b}{c} \right\rfloor ξ(i)= cai+b= c(a%c)i+(b%c)+i ca+ cb

∑ i = 0 n ⌊   a i + b c ⌋ = ∑ i = 0 n ( ⌊   ( a % c ) i + ( b % c ) c ⌋ + i ⌊   a c ⌋ + ⌊   b c ⌋ ) \sum\limits_{i=0}^n \left\lfloor\ \frac{ai+b}{c} \right\rfloor=\sum\limits_{i=0}^n (\left\lfloor\ \frac{(a\%c)i+(b\%c)}{c}\right\rfloor+i\left\lfloor\ \frac{a}{c} \right\rfloor+\left\lfloor\ \frac{b}{c} \right\rfloor) i=0n cai+b=i=0n( c(a%c)i+(b%c)+i ca+ cb)

有没有发现 ∑ i = 0 n ⌊   ( a % c ) i + ( b % c ) c ⌋ \sum\limits_{i=0}^n \left\lfloor\ \frac{(a\%c)i+(b\%c)}{c}\right\rfloor i=0n c(a%c)i+(b%c)也同样是一个一个 φ \varphi φ函数?他对应着 φ ( a % c , b % c , c , n ) \varphi(a\%c, b\%c,c,n) φ(a%c,b%c,c,n)

于是我们可以得到一个很强的结论:

φ ( a , b , c , n ) = φ ( a % c , b % c , c , n ) + n ( n + 1 ) 2 ⌊   a c ⌋ + ( n + 1 ) ⌊   b c ⌋ \varphi(a,b,c,n)=\varphi(a\%c,b\%c,c,n)+\frac{n(n+1)}{2} \left\lfloor\ \frac{a}{c} \right\rfloor + (n+1)\left\lfloor\ \frac{b}{c} \right\rfloor φ(a,b,c,n)=φ(a%c,b%c,c,n)+2n(n+1) ca+(n+1) cb

这样我们就把 a , b ≥ c a,b≥c a,bc的情况转化成了 a , b &lt; c a,b&lt;c a,b<c

a , b &lt; c a,b&lt;c a,b<c 时,显然 ξ ( i ) \xi(i) ξ(i)必定小于 n n n,这样我们可以变换使得上界变为 ξ ( i ) \xi(i) ξ(i),保证从原问题转化到的问题集变小

之后我们发现我们不会做了,考虑该问题的集合意义

a i + b c \frac{ai+b}{c} cai+b 表示在坐标系上其实是一个一次函数(线段),而我们的答案就是该线段以下的整点(坐标为整数)的点的个数

然后按照这样的思路我们重新构造一下 φ \varphi φ

∑ i = 0 n ⌊   a i + b c ⌋ = ∑ i = 0 n ∑ d = 1 ⌊   a n + b c ⌋ [ ⌊   a i + b c ⌋ ≥ d ] \sum\limits_{i=0}^n \left\lfloor\ \frac{ai+b}{c} \right\rfloor = \sum\limits_{i=0}^n \sum\limits_{d=1}^{\left\lfloor\ \frac{an+b}{c} \right\rfloor}[\left\lfloor\ \frac{ai+b}{c} \right\rfloor ≥ d] i=0n cai+b=i=0nd=1 can+b[ cai+bd]

= ∑ i = 0 n ∑ d = 0 ⌊   a n + b c ⌋ − 1 [ c ⌊ a i + b c ⌋ a ≥ c ( d + 1 ) a &gt; ( c d + c − 1 ) a ] =\sum\limits_{i=0}^n \sum\limits_{d=0}^{\left\lfloor\ \frac{an+b}{c} \right\rfloor-1}[ \frac{c \left\lfloor \frac{ai+b}{c}\right\rfloor}{a} ≥ \frac{c(d+1)}{a} &gt; \frac{(cd+c-1)}{a}] =i=0nd=0 can+b1[accai+bac(d+1)>a(cd+c1)]

= ∑ i = 0 n ∑ d = 0 ⌊   a n + b c ⌋ − 1 [ i &gt; c d + c − b − 1 a ] =\sum\limits_{i=0}^n \sum\limits_{d=0}^{\left\lfloor\ \frac{an+b}{c} \right\rfloor-1}[i&gt;\frac{cd+c-b-1}{a}] =i=0nd=0 can+b1[i>acd+cb1]

后面[]中的元素其实就是统计大于 c d + c − b − 1 a \frac{cd+c-b-1}{a} acd+cb1的i的个数,其恰好看做 n − ⌊ c d + c − b − 1 a ⌋ n-\left\lfloor \frac{cd+c-b-1}{a} \right\rfloor nacd+cb1(好巧),因此不难看出我们可以吧原式华为与i无关的和式:

原式 = ∑ d = 0 ⌊   a n + b c ⌋ − 1 n − ⌊ c d + c − b − 1 a ⌋ = \sum\limits_{d=0}^{\left\lfloor\ \frac{an+b}{c}\right\rfloor-1} n-\left\lfloor \frac{cd+c-b-1}{a} \right\rfloor =d=0 can+b1nacd+cb1

= n ⌊ a n + b c ⌋ − ∑ d = 0 ⌊   a n + b c ⌋ − 1 ⌊ c d + c − b − 1 a ⌋ = n\left\lfloor \frac{an+b}{c} \right\rfloor - \sum\limits_{d=0}^{\left\lfloor\ \frac{an+b}{c}\right\rfloor-1} \left\lfloor \frac{cd+c-b-1}{a} \right\rfloor =ncan+bd=0 can+b1acd+cb1

= n ⌊ a n + b c ⌋ − φ ( c , c − b − 1 , a , ⌊ a n + b c ⌋ − 1 ) =n\left\lfloor \frac{an+b}{c} \right\rfloor - \varphi(c,c-b-1,a,\left\lfloor \frac{an+b}{c} \right\rfloor-1) =ncan+bφ(c,cb1,a,can+b1)

因此,我们推出来了 φ ( a , b , c , n ) = φ ( c , c − b − 1 , a , ξ ( n ) − 1 ) \varphi(a,b,c,n)=\varphi(c,c-b-1,a,\xi(n)-1) φ(a,b,c,n)=φ(c,cb1,a,ξ(n)1)

通过上式,我们能够在 O ( l o g a ) O(loga) O(loga)内计算出 φ \varphi φ的值(因为其计算的本质是 gcd ⁡ \gcd gcd,故时间复杂度也相同)

当然边界为 a = 0 a=0 a=0没话说

放一小段程序:


ll f(ll a, ll b, ll c, ll n) {
	if (!a) return (n + 1) * (b / c) % MOD ;
	if (a >= c || b >= c) return (f(a % c, b % c, c, n) + (a / c) * n % MOD * (n + 1) % MOD * inv2 % MOD + (b / c) * (n + 1) % MOD) % MOD ;
	ll m = (a * n + b) / c ;
	return (n * m % MOD - f(c, c - b - 1, a, m - 1)) % MOD ;
}

之后考虑 ψ \psi ψ,根据上一题的研究方法,我们肯定也是先研究 a , b ≥ c a,b \ge c a,bc的情况

通过 φ \varphi φ的结论我们能够对 ψ \psi ψ做第一步变换:

ψ ( a , b , c , n ) = ∑ i = 0 n ( ⌊ ( ( a % c ) i + ( b % c ) c ⌋ + i ⌊ a c ⌋ + ⌊ b c ⌋ ) 2 \psi(a,b,c,n)=\sum\limits_{i=0}^n(\lfloor \frac{((a\%c)i+(b\%c)}{c} \rfloor+i\lfloor \frac{a}{c}\rfloor+\lfloor \frac{b}{c} \rfloor)^2 ψ(a,b,c,n)=i=0n(c((a%c)i+(b%c)+ica+cb)2

= ∑ i = 0 n ( i 2 ⌊ a c ⌋ + ⌊ b c ⌋ 2 + ⌊ ( a % c ) i + ( b % c ) c ⌋ + 2 i ⌊ a c ⌋ ⌊ ( a % c ) i + ( b % c ) c ⌋ + 2 ⌊ b c ⌋ ⌊ ( a % c ) i + ( b % c ) c ⌋ + 2 i ⌊ a c ⌋ ⌊ b c ⌋ ) =\sum\limits_{i=0}^n(i^2\lfloor \frac{a}{c} \rfloor+\lfloor \frac{b}{c} \rfloor^2+\lfloor \frac{(a\%c)i+(b\%c)}{c} \rfloor+2i\lfloor \frac{a}{c} \rfloor\lfloor \frac{(a\%c)i+(b\%c)}{c} \rfloor+2\lfloor \frac{b}{c} \rfloor \lfloor \frac{(a\%c)i+(b\%c)}{c} \rfloor+2i\lfloor \frac{a}{c} \rfloor\lfloor \frac{b}{c} \rfloor) =i=0n(i2ca+cb2+c(a%c)i+(b%c)+2icac(a%c)i+(b%c)+2cbc(a%c)i+(b%c)+2icacb)

观察式子,哪些是我们已经可以求得的

我们发现 i 2 i^2 i2可以通过公式直接求, ⌊ ( a % c ) i + ( b % c ) c ⌋ \lfloor \frac{(a\%c)i+(b\%c)}{c} \rfloor c(a%c)i+(b%c)显然就是 φ ( a % c , b % c , c , n ) \varphi(a \%c,b\%c,c,n) φ(a%c,b%c,c,n) ⌊ ( a % c ) i + ( b % c ) c ⌋ 2 \lfloor \frac{(a\%c)i+(b\%c)}{c} \rfloor^2 c(a%c)i+(b%c)2 ψ ( a % c , b % c , c , n ) \psi(a \%c,b\%c,c,n) ψ(a%c,b%c,c,n)

那么 i ⌊ ( a % c ) i + ( b % c ) c ⌋ i\lfloor \frac{(a\%c)i+(b\%c)}{c} \rfloor ic(a%c)i+(b%c)怎么求? 他实际就是 ϕ ( a % c , b % c , c , n ) \phi(a \%c,b\%c,c,n) ϕ(a%c,b%c,c,n)

既然要求出 ψ \psi ψ需要用到 ϕ \phi ϕ,那么我们就赶紧对 ϕ \phi ϕ做一些处理

S k ( n ) = ∑ i = 1 n i k S_k(n)=\sum\limits_{i=1}^ni^k Sk(n)=i=1nik,则可以吧求和符号消去:

ψ ( a , b , c , n ) = ψ ( a % c , b % c , c , n ) + ⌊ a c ⌋ 2 S 2 ( n ) + ( n + 1 ) ⌊ b c ⌋ 2 + 2 ⌊ a c ⌋ ϕ ( a % c , b % c , c , n ) + 2 ⌊ b c ⌋ ψ ( a % c , b % c , c , n ) + 2 ⌊ a c ⌋ ⌊ b c ⌋ S 1 ( n ) \psi(a,b,c,n)=\psi(a\%c,b\%c,c,n)+\lfloor \frac{a}{c}\rfloor^2S_2(n)+(n+1)\lfloor \frac{b}{c}\rfloor^2+2\lfloor \frac{a}{c}\rfloor\phi(a\%c,b\%c,c,n)+2\lfloor \frac{b}{c}\rfloor\psi(a\%c,b\%c,c,n)+2\lfloor \frac{a}{c}\rfloor\lfloor \frac{b}{c}\rfloor S_1(n) ψ(a,b,c,n)=ψ(a%c,b%c,c,n)+ca2S2(n)+(n+1)cb2+2caϕ(a%c,b%c,c,n)+2cbψ(a%c,b%c,c,n)+2cacbS1(n)

ψ ( a , b , c , n ) = ∑ i = 0 n ∑ d = 1 ⌊ a n + b c ⌋ 2 [ ⌊ a i + b c ⌋ 2 ≥ d ] \psi(a,b,c,n)=\sum\limits_{i=0}^n\sum\limits_{d=1}^{\lfloor \frac{an+b}{c}\rfloor^2}[\lfloor \frac{ai+b}{c}\rfloor^2 \ge d] ψ(a,b,c,n)=i=0nd=1can+b2[cai+b2d]

注意到这个式不能计算,原因是只保证 ξ ( n ) ≤ n \xi(n) \le n ξ(n)n,但是 x i ( n ) 2 xi(n)^2 xi(n)2就可能是 n 2 n^2 n2级别的,我们要是用一些小技巧

显然通过等差数列 X 2 = − X + 2 ∑ i = 1 x i X^2=-X+2\sum_{i=1}^xi X2=X+2i=1xi

那么上述式子等价于

∑ i = 0 n 2 ∑ d = 1 ⌊ a i + b c ⌋ d − ⌊ a i + b c ⌋ \sum\limits_{i=0}^n2\sum\limits_{d=1}^{\lfloor \frac{ai+b}{c}\rfloor}d-\lfloor \frac{ai+b}{c}\rfloor i=0n2d=1cai+bdcai+b

= 2 ∑ d = 0 ⌊ a n + b c ⌋ − 1 ( d + 1 ) ∑ i = 0 n [ a i + b c ≥ d + 1 ] − ⌊ a i + b c ⌋ =2\sum\limits_{d=0}^{\lfloor \frac{an+b}{c}\rfloor-1}(d+1)\sum\limits_{i=0}^n[\frac{ai+b}{c} \ge d+1]-\lfloor \frac{ai+b}{c}\rfloor =2d=0can+b1(d+1)i=0n[cai+bd+1]cai+b

= 2 ∑ d = 0 ⌊ a n + b c ⌋ − 1 ( d + 1 ) ∑ i = 0 n [ i &gt; c d + c − b − 1 a ] − φ ( a , b , c , n ) =2\sum\limits_{d=0}^{\lfloor \frac{an+b}{c}\rfloor-1}(d+1)\sum\limits{i=0}^n[i&gt;\frac{cd+c-b-1}{a}]-\varphi(a,b,c,n) =2d=0can+b1(d+1)i=0n[i>acd+cb1]φ(a,b,c,n)

= 2 ∑ d = 0 ⌊ a n + b c ⌋ − 1 ( d + 1 ) ( n − ⌊ c d + c − b − 1 a ⌋ ) − φ ( a , b , c , n ) =2\sum\limits_{d=0}^{\lfloor \frac{an+b}{c}\rfloor-1}(d+1)(n-\lfloor \frac{cd+c-b-1}{a}\rfloor)-\varphi(a,b,c,n) =2d=0can+b1(d+1)(nacd+cb1)φ(a,b,c,n)

= 2 ∑ d = 0 ⌊ a n + b c ⌋ − 1 ( d + 1 ) ( n − ⌊ c d + c − b − 1 a ⌋ ) − φ ( a , b , c , n ) =2\sum\limits_{d=0}^{\lfloor \frac{an+b}{c}\rfloor-1}(d+1)(n-\lfloor \frac{cd+c-b-1}{a}\rfloor)-\varphi(a,b,c,n) =2d=0can+b1(d+1)(nacd+cb1)φ(a,b,c,n)

= 2 n ∑ d = 0 ⌊ a n + b c ⌋ − 1 ( d + 1 ) − 2 ∑ d = 0 ⌊ a n + b c ⌋ − 1 ( d + 1 ) [ c d + c − b − 1 a ] − φ ( a , b , c , n ) =2n\sum\limits_{d=0}^{\lfloor \frac{an+b}{c}\rfloor-1}(d+1)-2\sum\limits_{d=0}^{\lfloor \frac{an+b}{c}\rfloor-1}(d+1)[\frac{cd+c-b-1}{a}]-\varphi(a,b,c,n) =2nd=0can+b1(d+1)2d=0can+b1(d+1)[acd+cb1]φ(a,b,c,n)

= n ξ ( n ) ( ξ ( n ) + 1 ) − 2 ϕ ( c , c − b − 1 , a , ξ ( n ) − 1 ) − 2 φ ( c , c − b − 1 , a , ξ ( n ) − 1 ) − φ ( a , b , c , n ) =n\xi(n)(\xi(n)+1)-2\phi(c,c-b-1,a,\xi(n)-1)-2\varphi(c,c-b-1,a,\xi(n)-1)-\varphi(a,b,c,n) =nξ(n)(ξ(n)+1)2ϕ(c,cb1,a,ξ(n)1)2φ(c,cb1,a,ξ(n)1)φ(a,b,c,n)

通过上述推导,我们就把 ψ \psi ψ成功转化成了 ϕ \phi ϕ,并且 n n n的规模减小了

φ ( a , b , c , n ) = n ξ ( n ) ( ξ ( n ) + 1 ) − 2 ϕ ( c , c − b − 1 , a , ξ ( n ) − 1 ) − 2 φ ( c , c − b − 1 , a , ξ ( n ) − 1 ) − φ ( a , b , c , n ) \varphi(a,b,c,n)=n\xi(n)(\xi(n)+1)-2\phi(c,c-b-1,a,\xi(n)-1)-2\varphi(c,c-b-1,a,\xi(n)-1)-\varphi(a,b,c,n) φ(a,b,c,n)=nξ(n)(ξ(n)+1)2ϕ(c,cb1,a,ξ(n)1)2φ(c,cb1,a,ξ(n)1)φ(a,b,c,n)

最后,我们只需求出 ϕ \phi ϕ即可,非常简单,按照惯例,我满依然将 a , b ≥ c a,b \ge c a,bc的情形进行转换。我们直接推出结论:

ϕ ( a , b , c , n ) = ⌊ a c ⌋ S 2 ( n ) + ⌊ b c ⌋ S 1 ( n ) + ϕ ( a % c , b % c , c , n ) \phi(a,b,c,n)=\lfloor \frac{a}{c}\rfloor S_2(n)+\lfloor \frac{b}{c}\rfloor S_1(n)+\phi(a\%c,b\%c,c,n) ϕ(a,b,c,n)=caS2(n)+cbS1(n)+ϕ(a%c,b%c,c,n)

a , b &lt; c a,b &lt; c a,b<c的情况也类似,用 ξ \xi ξ 替代原式,这里同样十分简单,过程与上面相同,

ϕ ( a , b , c , n ) = 2 ξ ( n ) S 1 ( n ) − φ ( c , c − b − 1 , a , ξ ( n ) − 1 ) − ψ ( c , c − b − 1 , a , ξ ( n ) − 1 ) 2 \phi(a,b,c,n)=\frac{2\xi(n)S_1(n)-\varphi(c,c-b-1,a,\xi(n)-1)-\psi(c,c-b-1,a,\xi(n)-1)}{2} ϕ(a,b,c,n)=22ξ(n)S1(n)φ(c,cb1,a,ξ(n)1)ψ(c,cb1,a,ξ(n)1)

通过上述方式我们即可求解上述三式

还有个高次放求和

这是个表
在这里插入图片描述
我们知道 ∑ i = 1 n C i k = C n + 1 k + 1 \sum\limits_{i=1}^nC_i^k=C_{n+1}^{k+1} i=1nCik=Cn+1k+1
∑ i = 1 n i 2 = ∑ i = 1 n i ( i − 1 ) + i = 2 ∗ ∑ i = 1 n C i 2 + ∑ i = 1 n C i 1 = 2 C n + 1 3 + C n + 1 2 = n ∗ ( n + 1 ) ∗ ( 2 n + 1 ) 6 \sum\limits_{i=1}^ni^2=\sum\limits_{i=1}^ni(i-1)+i=2*\sum\limits_{i=1}^nC_i^2+\sum\limits_{i=1}^nC_i^1=2C_{n+1}^3+C_{n+1}^2=\frac{n*(n+1)*(2n+1)}{6} i=1ni2=i=1ni(i1)+i=2i=1nCi2+i=1nCi1=2Cn+13+Cn+12=6n(n+1)(2n+1)

来看逆元吧

因为模不支持除法,为此,我们引入乘法逆元来解决问题

对于正整数 a a a m m m,如果 a x ≡ 1 ( m o d   m ) ax≡1(mod \ m) ax1(mod m),则 x x x的最小整整数解为 a a a m m m意义下的逆元,记做 a − 1 a^{-1} a1

求解逆元有3种方法

第一种:费马小定理

费马小定理: a p − 1 ≡ 1 ( m o d   p ) a^{p-1}≡1(mod \ p) ap11(mod p)其中必须保证p为质数

所以 a ∗ a p − 2 ≡ 1 ( m o d   p ) a*a^{p-2}≡1(mod \ p) aap21(mod p),即 a p − 2 a^{p-2} ap2即为逆元

    int getinv(int a, int p) { // inv = a ^ (p - 2)
    	return power(a, p - 2,  p) ; // 调用快速幂
    }

第二种:扩展欧几里得

根据逆元定义可以转化成丢番图方程 a x + p y = 1 ax+py=1 ax+py=1

然后解这个方程即可

gcd ⁡ ( a , p ) ≠ 1 \gcd(a,p)≠1 gcd(a,p)̸=1时,方程无解

这告诉我们,存在逆元的前提是 gcd ⁡ ( a , p ) = 1 \gcd(a,p)=1 gcd(a,p)=1

    int getinv(int a, int p) { // 可以求出单个inv
    	ll x, y ;
    	ll d = exgcd(a, p, x, y) ;
    	return d == 1 ? (x + p) % p ? -1 ;
    }

第三种:线性递推

a − 1 = − ⌊   m a ⌋ ∗ ( m % a ) − 1 a^{-1}=-\left\lfloor\ \frac{m}{a}\right\rfloor*(m\%a)^{-1} a1= am(m%a)1

证明:设 m = k a + r ( r &lt; a ) m=ka+r(r&lt;a) m=ka+r(r<a),则 k = ⌊ m a ⌋ k=\left\lfloor \frac{m}{a}\right\rfloor k=am r = m % a r=m\%a r=m%a

因为 k a + r ≡ 0 ( m o d   m ) ka+r≡0(mod \ m) ka+r0(mod m),所以两边同时乘以 a − 1 r − 1 a^{-1}r^{-1} a1r1得:

k r − 1 + a − 1 ≡ 0 ( m o d   m ) kr^{-1}+a^{-1}≡0(mod \ m) kr1+a10(mod m)

a − 1 ≡ − k r − 1 ≡ − ⌊   m a ⌋ ∗ ( m % a ) ( m o d   m ) a^{-1}≡-kr^{-1}≡-\left\lfloor\ \frac{m}{a}\right\rfloor*(m\%a)(mod \ m) a1kr1 am(m%a)(mod m)

时间复杂度 O ( n ) O(n) O(n),非常优秀

    void initinv(int n, int p) {
    	inv[1] = 1 ;
    	for (int i = 2; i <= n; i++) inv[i] = (ll) (p - p / i) * inv[p % i] % p ;
    }
中国剩余定理

给定 n n n个同余方程( m 1 , m 2 , . . . , m n m_1,m_2,...,m_n m1,m2,...,mn两两互质)
{ x ≡ a 1 ( m o d   m 1 ) x ≡ a 2 ( m o d   m 2 ) . . . . x ≡ a n ( m o d   m n ) \begin{cases} x≡a_1(mod \ m_1) \\ x≡a_2(mod \ m_2) \\ .... \\ x≡a_n(mod \ m_n) \end{cases} xa1(mod m1)xa2(mod m2)....xan(mod mn)

M = ∏ i = 1 n m i M=\prod\limits_{i=1}^nm_i M=i=1nmi,则满足上述方程的 x x x的值为 x = ∑ i = 1 n a i M m i M m i − 1 x=\sum\limits_{i=1}^na_i\frac{M}{m_i}\frac{M}{m_i}^{-1} x=i=1naimiMmiM1,其中 M m i − 1 \frac{M}{m_i}^{-1} miM1表示 M m i \frac{M}{m_i} miM在模 m i m_i mi意义下的乘法逆元

代入显然正确

互质模板题 [TJOI2009]猜数字

CRT的题目都尽量用龟速乘吧,防止爆longlong

板子直接上

int n ;
ll a[N], b[N], r[N], m[N] ;
ll x, y ;

void exgcd(ll a, ll b, ll &x, ll &y) { // exgcd解出逆元
	if (!b) {
		x = 1 ; y = 0 ;
		return ;
	}
	exgcd(b, a % b, y, x) ;
	y -= (a / b) * x ;
}

ll mul(ll a, ll b, ll MOD) { // 最后一个点爆long long 要用龟速乘
	ll ans = 0 ;
	for(; b; b >>= 1, a = (a + a) % MOD) if (b & 1) ans = (ans + a) % MOD ;
	return ans ;
}

void china() {
	ll sum = 1, ans = 0 ;
	rep(i, 1, n) sum *= b[i] ; // 求lcm
	rep(i, 1, n) m[i] = sum / b[i] ; // 除一下
	rep(i, 1, n) {
		exgcd(m[i], b[i], x, y) ;
		r[i] = (x % b[i] + b[i]) % b[i] ; 
		// r[i]为m[i]的逆元,(r[i]=x)*m[i]≡1(% b[i]) -> r[i]*m[i]+b[i]*y=1
	}
	rep(i, 1, n) ans= (ans + mul(mul(a[i], m[i], sum), r[i], sum)) % sum ; // ans = Σ a[i]*m[i]*r[i]
	if (ans < 0) ans += sum ;
	printf("%lld\n", ans) ;
}

signed main(){
    scanf("%d", &n) ;
    rep(i, 1, n) scanf("%lld", &a[i]) ;
    rep(i, 1, n) scanf("%lld", &b[i]) ;
	china() ;
	return 0 ;
}

那如果模数不是两两互质的呢?

发现上述式子失效,只能另辟蹊径

设目前解除前 k − 1 k-1 k1个方程的解为 x x x

M = L C M i = 1 k − 1 m i M=LCM_{i=1}^{k-1}m_i M=LCMi=1k1mi

k − 1 k-1 k1个方程的通解 x + i ∗ M ( i ∈ Z ) x+i*M(i∈\Z) x+iM(iZ)

那么对于加入的第k个方程

我们要求出一个 t t t,使得 x + t ∗ M = a k ( m o d   m k ) x+t*M=a_k(mod \ m_k) x+tM=ak(mod mk)

转化一下得到 t ∗ M = a k − x ( m o d   m k ) t*M=a_k-x(mod \ m_k) tM=akx(mod mk)

对这个式子做exgcd就能够求出 t t t

若同余式无解,则方程组无解

否则前 k k k个方程的解 x k = x + t ∗ M x_k=x+t*M xk=x+tM

相当于做k次扩欧求

int n ;
ll A[N], B[N] ;

ll exgcd(ll a, ll b, ll &x, ll &y) {
	if (!b) {
		x = 1 ; y = 0 ;
		return a ;
	}
	ll d = exgcd(b, a % b, y, x) ;
	y -= (a / b) * x ;
	return d ;
}

ll mul(ll a, ll b, ll MOD) {
	ll res = 0 ;
	for (; b; b >>= 1, a = (ll)(a + a) % MOD) if (b & 1) res = (res + a) % MOD ;
	return res ;
}

ll exchina() {
	ll x, y, M = B[1], ans = A[1] ; // 一般特判第一条式子
	rep(i, 2, n) {
		ll a = M, b = B[i], c = (A[i] - ans % b + b) % b ;
		ll gcd = exgcd(a, b, x, y), nw = b / gcd ;
		// x * M(a) + y * B[i](b) = gcd(a,b) --> (A[i]-ans)
		if (c % gcd) return -1 ; // gcd|c,否则无解
		x = mul(x, c / gcd, nw) ; // x * ((A[i]-ans) / gcd)
		ans += x * M ; // ans += x * M
		M *= nw ; // 更新LCM
		ans = (ans % M + M) % M ; // 总的模数为M,模一下
	}
	return (ans % M + M) % M ;
}

signed main(){
	while (scanf("%d", &n) != EOF) {
		rep(i, 1, n) scanf("%lld%lld", &B[i], &A[i]) ;
		printf("%lld\n", exchina()) ;
	}
	return 0 ;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值