《算法竞赛进阶指南》数论篇

下述理论主要参考书目: 电子版pdf:算法竞赛进阶指南(p133-150)

文章目录

  • 下述理论主要参考书目: [电子版pdf:算法竞赛进阶指南(p133-150)](http://www.j9p.com/down/536233.html)
    • 首先补充两个前置知识:约数和最大约数有关性质,可选择性看~
    • 有关素数筛的算法 [埃式 n l o g ( n ) nlog(n) nlog(n)&欧拉素数筛 o ( n ) o(n) o(n)&大区间素数筛](https://blog.csdn.net/weixin_45819197/article/details/109545970)
    • 约数
    • 最大公约数
      • 1.gcd(a,b)=gcd(a,a-b)=gcd(b,a-b)=d;
      • 2.欧几里得算法: b!=0; gcd(a,b)=gcd(b,a%b)=d;
    • 欧拉函数
      • φ(N)=N*(1 - 1 p 1 \displaystyle\frac{1}{p_1} p11)(1 - 1 p 2 \displaystyle\frac{1}{p_2} p21)(1 - 1 p 3 \displaystyle\frac{1}{p_3} p31)......(1 - 1 p m \displaystyle\frac{1}{p_m} pm1)
      • 欧拉函数的一些性质
        • 2.性质2我们知道了欧拉函数是积性函数(PS:积性函数:对于任意互质的整数a和b有性质f(ab)=f(a)f(b)的数论函数)
        • 3.p 为质数,若p|n 且 p 2 p^2 p2|n,则φ(n)= φ ( n p ) ∗ p φ(\displaystyle\frac{n}{p})*p φ(pn)p;
        • 4.p 为质数,若p|n 且 p 2 p^2 p2不n整除,则φ(n)= φ ( n p ) ∗ ( p − 1 ) φ(\displaystyle\frac{n}{p})*(p-1) φ(pn)(p1);
        • 5. ∑ d ∣ n φ ( d ) = n \sum_{d|n}φ(d)=n dnφ(d)=n
    • 同余
      • 同余的基本性质
        • 性质一: 如果a ≡ \equiv b(mod m),c ≡ \equiv d(mod m).那么( a ± c a\pm c a±c) ≡ \equiv ( b ± d b \pm d b±d) (mod m)。
        • 性质二:如果a ≡ \equiv b(mod m),c ≡ \equiv d(mod m).那么( a ∗ c a*c ac) ≡ \equiv ( b ∗ d b*d bd) (mod m)。
        • 性质三: 如果ac ≡ \equiv bc(mod m), 且 gcd(c,m)=1(c和m互质) , 则有a ≡ \equiv b(mod m)。
        • 性质四:若ac≡bd,c≡d(mod m),且gcd(c,m)=1,得到a≡b(mod m)。
      • 同余类与剩余系
    • 费马小定理 & 欧拉定理
      • 趁热打铁来一道关于BSBG的算法题(依据费马下定理)
        • [Discrete Logging POJ - 2417 ](https://vjudge.net/problem/POJ-2417)
    • 欧拉定理的推论
      • 最小正整数 x 0 x_0 x0
      • 欧拉的指数循环节
    • 其他理论
      • 来看一到题:[余数之和](https://www.acwing.com/problem/content/201/)

首先补充两个前置知识:约数和最大约数有关性质,可选择性看~

有关素数筛的算法 埃式 n l o g ( n ) nlog(n) nlog(n)&欧拉素数筛 o ( n ) o(n) o(n)&大区间素数筛

约数

《算法竞赛进阶指南》数论篇_第1张图片

最大公约数

1.gcd(a,b)=gcd(a,a-b)=gcd(b,a-b)=d;

2.欧几里得算法: b!=0; gcd(a,b)=gcd(b,a%b)=d;

(ps:其实这里有个一般性的结论:gcd(m, n n n)=gcd(m, k ∗ m + r 1 k*m+r_1 km+r1),n= k ∗ m + r 1 k*m+r_1 km+r1,k为整数,0<= r 1 r_1 r1

1.证明:d|a 且 d|b 那么d| (a-b) 得证

2.证明:a a>=b: 令 a= q ∗ b q*b qb+r;
由于d|a d| ( q ∗ b ) (q*b) (qb)
那么易得 d|(a- q ∗ b q*b qb) 即得d|r
又r=a mod b ,所以gcd(a,b)=gcd(b,a%mod);

欧拉函数

φ(N)=N*(1 - 1 p 1 \displaystyle\frac{1}{p_1} p11)(1 - 1 p 2 \displaystyle\frac{1}{p_2} p21)(1 - 1 p 3 \displaystyle\frac{1}{p_3} p31)…(1 - 1 p m \displaystyle\frac{1}{p_m} pm1)

《算法竞赛进阶指南》数论篇_第2张图片

证明
《算法竞赛进阶指南》数论篇_第3张图片
具体用到了容斥原理:
φ(N)=N - ( N p 1 \displaystyle\frac{N}{p_1} p1N + N p 2 \displaystyle\frac{N}{p_2} p2N + N p 3 \displaystyle\frac{N}{p_3} p3N + N p 4 \displaystyle\frac{N}{p_4} p4N- N p 1 p 2 \displaystyle\frac{N}{p_1p_2} p1p2N - N p 2 p 3 \displaystyle\frac{N}{p_2p_3} p2p3N- N p 1 p 3 \displaystyle\frac{N}{p_1p_3} p1p3N - N p 1 p 4 \displaystyle\frac{N}{p_1p_4} p1p4N - N p 2 p 4 \displaystyle\frac{N}{p_2p_4} p2p4N - N p 3 p 4 \displaystyle\frac{N}{p_3p_4} p3p4N + N p 1 p 2 p 3 \displaystyle\frac{N}{p_1p_2p_3} p1p2p3N + N p 1 p 2 p 4 \displaystyle\frac{N}{p_1p_2p_4} p1p2p4N…-…+…-… N p 1 p 2 p 3 . . . . . . p m \displaystyle\frac{N}{p_1p_2p_3......p_m} p1p2p3......pmN)
(ps:分式这小东西麻烦啦啊aaa…)
上面的式子因式分解就得到了:《算法竞赛进阶指南》数论篇_第4张图片
即是: φ(N)=N*(1 - 1 p 1 \displaystyle\frac{1}{p_1} p11)(1 - 1 p 2 \displaystyle\frac{1}{p_2} p21)(1 - 1 p 3 \displaystyle\frac{1}{p_3} p31)…(1 - 1 p m \displaystyle\frac{1}{p_m} pm1)

欧拉函数的一些性质

《算法竞赛进阶指南》数论篇_第5张图片

2.性质2我们知道了欧拉函数是积性函数(PS:积性函数:对于任意互质的整数a和b有性质f(ab)=f(a)f(b)的数论函数)
3.p 为质数,若p|n 且 p 2 p^2 p2|n,则φ(n)= φ ( n p ) ∗ p φ(\displaystyle\frac{n}{p})*p φ(pn)p;
4.p 为质数,若p|n 且 p 2 p^2 p2不n整除,则φ(n)= φ ( n p ) ∗ ( p − 1 ) φ(\displaystyle\frac{n}{p})*(p-1) φ(pn)(p1);
5. ∑ d ∣ n φ ( d ) = n \sum_{d|n}φ(d)=n dnφ(d)=n

证明

1.由于gcd(n,x)=gcd(n,n-x)=1,所以与n互质的数是"成对"的出现。进而n+(n-x)=n. 就得出了
2.性质2就很显然了,根据欧拉函数的公式 φ(N). a,b互质,所以分解质因数没有一样的,根据欧拉函数就可以将 φ(a) φ(b)合并得出了φ(N)。
所以欧拉函数是积性函数
3.用到了 φ(N)=N ∗ * (1 - 1 p 1 \displaystyle\frac{1}{p_1} p11)(1 - 1 p 2 \displaystyle\frac{1}{p_2} p21)(1 - 1 p 3 \displaystyle\frac{1}{p_3} p31)…(1 - 1 p m \displaystyle\frac{1}{p_m} pm1)
p 2 p^2 p2|n主要告诉咱们N分解后p的质因数个数不少于2. 所以 N p \displaystyle\frac{N}{p} pN分解后的质因数还有p.
φ( N N N)和φ( N p \displaystyle\frac{N}{p} pN)的欧拉函数表达式中(1 - 1 p i \displaystyle\frac{1}{p_i} pi1)全都一样,只是一个是N和 N p \displaystyle\frac{N}{p} pN
所以就得出了φ(N)= φ ( N p ) ∗ p φ(\displaystyle\frac{N}{p})*p φ(pN)p;
4.是同理3的证明方法。
5.性质5: f ( n ) = ∑ d ∣ n φ ( d ) = n f(n)=\sum_{d|n}φ(d)=n f(n)=dnφ(d)=n 证明比较难了,首先得证明 f ( n ) f(n) f(n)是积性函数. f ( n ) f(n) f(n)积性函数证明:其实有点显然了, 若n,m互质,出发点仍然是质因数分解考虑. 举个栗子:n=6, m=35, n,m互质.
n中的d:1,2,3. m中的d:1,5,7. 然后我们知道欧拉函数 φ(N)是个积性函数(见性质2)。
( 1 , 2 , 3 ) ∗ ( 1 , 5 , 7 ) (1,2,3)*(1,5,7) (1,2,3)(1,5,7)的分解得出集合d全是能整除 n ∗ m n*m nm,不多不少。 ps: ( 1 , 2 , 3 ) ∗ ( 1 , 5 , 7 ) (1,2,3)*(1,5,7) (1,2,3)(1,5,7) 得到的d集合(1,5,7,2,10,14,3,15,21).
所以就知道了嘛: n,m互质 那么: f ( n ∗ m ) = f ( n ) f ( m ) f(n*m)=f(n)f(m) f(nm)=f(n)f(m) 得证: f ( n ) f(n) f(n)是积性函数

《算法竞赛进阶指南》数论篇_第6张图片
ps:φ(1)=1

同余

定义:若整数a和整数b除以正整数m的余数相等,则称a,b模m同余。记为a ≡ \equiv b(mod m)。
eg:10 ≡ \equiv 24(mod 7) 同余数3.

同余的基本性质

在写性质之前,先得有种这样的思路。
a= p ∗ m p*m pm+ r 1 r_1 r1
b= q ∗ m q*m qm+ r 2 r_2 r2
如果a ≡ \equiv b(mod m),那么 r 1 r_1 r1= r 2 r_2 r2

性质一: 如果a ≡ \equiv b(mod m),c ≡ \equiv d(mod m).那么( a ± c a\pm c a±c) ≡ \equiv ( b ± d b \pm d b±d) (mod m)。

(ps:从 r 1 r_1 r1 r 2 r_2 r2这方面思考)。

性质二:如果a ≡ \equiv b(mod m),c ≡ \equiv d(mod m).那么( a ∗ c a*c ac) ≡ \equiv ( b ∗ d b*d bd) (mod m)。

证明: 首先从已知得到a和b的余数是 r 1 r_1 r1,c和d的余数是 r 2 r_2 r2.
a= p ∗ m p*m pm+ r 1 r_1 r1, c= q ∗ m q*m qm+ r 2 r_2 r2
然后呢 a ∗ c a*c ac= p ∗ q ∗ m p*q*m pqm + ( r 1 + r 2 ) ∗ m (r_1+r_2)*m (r1+r2)m + r 1 ∗ r 2 r_1*r_2 r1r2.
对于 b ∗ d b*d bd同理的,那些( p ∗ q ∗ m p*q*m pqm + ( r 1 + r 2 ) ∗ m (r_1+r_2)*m (r1+r2)m)能被整除的不用管它,然后后面的尾巴都是 r 1 ∗ r 2 r_1*r_2 r1r2.所以得以证明。

性质三: 如果ac ≡ \equiv bc(mod m), 且 gcd(c,m)=1(c和m互质) , 则有a ≡ \equiv b(mod m)。

这条性质很重要,反复品味。
证明: 对于ac ≡ \equiv bc(mod m)有ac= p ∗ m p*m pm+ r 1 r_1 r1,bc= q ∗ m q*m qm+ r 1 r_1 r1
所以ac- p ∗ m p*m pm=bc- q ∗ m q*m qm.
得到: ( a − b ) ∗ c (a-b)*c (ab)c= ( p − q ) ∗ m (p-q)*m (pq)m
再可得到 ( a − b ) ∗ c (a-b)*c (ab)c中能被m整除。
然后根据算术基本定理:n= p 1 c 1 p_{1}^{c_1} p1c1 p 2 c 2 p_{2}^{c_2} p2c2 p 3 c 3 p_{3}^{c_3} p3c3 p 4 c 4 p_{4}^{c_4} p4c4 p m c m p_{m}^{c_m} pmcm
由于gcd(c,m)=1, m不在c中,那么m只能在 a − b a-b ab中。(即是 a − b a-b ab= k ∗ m k*m km)
用符号表示:m|(a-b).
a= p ∗ m p*m pm+ r 1 r_1 r1
b= q ∗ m q*m qm+ r 2 r_2 r2
a-b= ( p − q ) ∗ m (p-q)*m (pq)m+ ( r 1 − r 2 ) (r_1-r_2) (r1r2)
能被m整除,所以 r 1 r_1 r1= r 2 r_2 r2
这就说明了a和b的余数都是 r 1 r_1 r1。 所以a ≡ \equiv b(mod m)。

性质四:若ac≡bd,c≡d(mod m),且gcd(c,m)=1,得到a≡b(mod m)。

(ps:其实性质三是性质四的特殊情况,c=d )
证明: 首先c与d的余数相等,记为 r 1 r_1 r1,
又因为gcd(c,m)=1;
所以 r 1 r_1 r1=1
所以我们得出了gcd(d,m)=1.
a= p ∗ m p*m pm+ r 2 r_2 r2
c= q ∗ m q*m qm+ 1 1 1
b= k ∗ m k*m km+ r 3 r_3 r3
ac=( p ∗ q ∗ m p*q*m pqm) + ( p ∗ m p*m pm) + ( q ∗ m ∗ r 1 q*m*r_1 qmr1) + r 2 r_2 r2
bd=…+ r 3 r_3 r3
由于ac与bd余数相等,所以 r 2 = r 3 r_2=r_3 r2=r3
所以a≡b(mod m)。

同余类与剩余系

《算法竞赛进阶指南》数论篇_第7张图片
gcd( a ∗ b a*b ab,m)=1; gcd( a ∗ b a*b ab,m)=gcd( ( a ∗ b ) (a*b) (ab)%m,m)=1. (ps:见最大公约数性质二)
所以 ( a ∗ b ) (a*b) (ab)%m 与 m互质。 所以得出了简化剩余系关于模m乘法封闭。
(ps:这个关系怎么理解呢?对于所有的a,gcd(a,m)=1,那么gcd(a%m,m)=1,即是所有a都能映射到m的简化剩余系中)

费马小定理 & 欧拉定理

1.费马小定理:若p是质数,则对于任意整数a,有 a p ≡ a a^p\equiv a apa(mod p)。
2.欧拉定理:若正整数a,n互质,则 a φ ( n ) ≡ 1 a^{φ(n)}\equiv 1 aφ(n)1(mod n).

ps:我个人一般会写成 a φ ( p ) ≡ 1 a^{φ(p)}\equiv 1 aφ(p)1(mod p).
证明
设n的简化剩余系为{ a 1 ‾ \overline{a_1} a1, a 2 ‾ \overline{a_2} a2, a 3 ‾ \overline{a_3} a3, ⋯ \cdots a φ ( n ) ‾ \overline{a_{φ(n)}} aφ(n)}。对于 ∀ a i , a j \forall a_i,a_j ai,aj,若 a ∗ a i ≡ a ∗ a j a*a_i\equiv a*a_j aaiaaj(mod n)。
根据同余性质三的结论(如果ac ≡ \equiv bc(mod m), 且 gcd(c,m)=1(c和m互质) , 则有a ≡ \equiv b(mod m)。) 可知道 a i ≡ a j a_i\equiv a_j aiaj (mod n)又因为 a i , a j ∈ ( 1 , n ) a_i,a_j\in(1,n) ai,aj(1,n),所以 a i ≠ a j a_i\neq a_j ai=aj
这个证明有什么用呢?意味着若 a i ≠ a j a_i \neq a_j ai=aj,则 ( a ∗ a i ) (a*a_i) (aai)%n和 ( a ∗ a j ) (a*a_j) (aaj)%n不等。
那么 a ∗ a i a*a_i aai等一系列是一一对应的。
因此,集合{ a 1 ‾ \overline{a_1} a1, a 2 ‾ \overline{a_2} a2, a 3 ‾ \overline{a_3} a3, ⋯ \cdots a φ ( n ) ‾ \overline{a_{φ(n)}} aφ(n)}与集合{ a a 1 ‾ \overline{aa_1} aa1, a a 2 ‾ \overline{aa_2} aa2, a a 3 ‾ \overline{aa_3} aa3, ⋯ \cdots a a φ ( n ) ‾ \overline{aa_{φ(n)}} aaφ(n)}都能表示n的简化剩余系。
所以我们得出了这样一个东东…
a φ ( n ) a 1 a 2 a 3 ⋯ a φ ( n ) ≡ ( a a 1 ) ( a a 2 ) ( a a 3 ) ⋯ a φ ( n ) a^{φ(n)}a_1a_2a_3\cdots a_{φ(n)}\equiv (aa_1)(aa_2)(aa_3)\cdots a_{φ(n)} aφ(n)a1a2a3aφ(n)(aa1)(aa2)(aa3)aφ(n)
( a a 1 ) ( a a 2 ) ( a a 3 ) ⋯ a φ ( n ) ≡ a 1 a 2 a 3 ⋯ a φ ( n ) (aa_1)(aa_2)(aa_3)\cdots a_{φ(n)}\equiv a_1a_2a_3\cdots a_{φ(n)} (aa1)(aa2)(aa3)aφ(n)a1a2a3aφ(n)(mod n)
a a 1 = p 1 ∗ m aa_1=p_1*m aa1=p1m+ r i r_i ri, a a 2 = p 2 ∗ m aa_2=p_2*m aa2=p2m+ r j r_j rj, a a 3 = p 3 ∗ m aa_3=p_3*m aa3=p3m+ r k r_k rk,然后像这样所有的 a a s aa_s aas的余数 r i , r j , ⋯ r k r_i,r_j,\cdots r_k ri,rj,rk组成的集合就是n的简化剩余系(ps:用到了上面证明的两个集合一一对应的性质,我相信您能看到这里对同余的理解应该很清楚了)就得出了上面的等式。
结合两个等式 a φ ( n ) a 1 a 2 a 3 ⋯ a φ ( n ) ≡ a 1 a 2 a 3 ⋯ a φ ( n ) a^{φ(n)}a_1a_2a_3\cdots a_{φ(n)}\equiv a_1a_2a_3\cdots a_{φ(n)} aφ(n)a1a2a3aφ(n)a1a2a3aφ(n)(mod n)
a 1 a 2 a 3 ⋯ a φ ( n ) a_1a_2a_3\cdots a_{φ(n)} a1a2a3aφ(n)与n互质(根据同余性质三)
得出了 a φ ( n ) ≡ 1 a^{φ(n)} \equiv 1 aφ(n)1(mod n)
在上述中我们的前提是a与n是互质的。故我们证明了欧拉定理。
如果n是质数,那么φ(n)=n-1。 在欧拉定理的基础上左右乘以a,得到 a n ≡ a a^n\equiv a ana(mod n)
即证明了费马小定理

趁热打铁来一道关于BSBG的算法题(依据费马下定理)

Discrete Logging POJ - 2417

问题: 给定 a , b , p , a,b,p, a,b,p,求最小非负整数x,满足 a x ≡ b a^x\equiv b axb(mod p p p)
p是质数。
x = i ∗ m − j , x=i*m -j, x=imj, m = ⌈ p ⌉ m=⌈\sqrt{p}⌉ m=p , 所以 a i m − j ≡ b a^{im-j}\equiv b aimjb(mod p)
左右边同乘以 a j a^j aj,得到: a i m ≡ b a j a^{im}\equiv ba^j aimbaj(mod p)
然后就可以枚举i和j了。
首先从 [ 0 , m ] [0,m] [0,m]枚举j,将得到的b a j a^j aj的值存入hash值。
然后,从 [ 1 − m ] [1-m] [1m]枚举 i i i,计算 a i m a^{im} aim,查表,如果有值与之相等,则得到的 i m − j im-j imj是最小值.
然后最小的非负数整数x若存在一定在1-p 区间内。
注意事项

1.为什么最小的非负数整数x若存在一定在 [ 1 , p ] [1,p] [1,p] 区间内
因为费马小定理: a p ≡ a a^p\equiv a apa(mod p) 进而得出 a p − 1 ≡ 1 a^{p-1}\equiv 1 ap11(mod p)
x=k*(p-1)+r. 1 所以: a x ≡ r a^x\equiv r axr(mod p p p)
这说明了什么呢,一个大于等于p的x,总能在r ∈ [ 1 , p − 1 ] \in [1,p-1] [1,p1],找出r。
2.为什么m要取 ⌈ n ⌉ ⌈\sqrt{n}⌉ n 就可以?
因为是枚举嘛,开根号的时间复杂度是多少的。
3.一点j点可能会被覆盖呀??对没错。枚举j时出来的值是有可能重复,那么在map就会再次刷新,
然后若是刷新啦,j刷新值会比原来值更大(ps:在代码中解释会更直观)。j值越大,得到的x越小( x = i ∗ m − j x=i*m -j x=imj),也是我们希望的。
4.关于枚举i,j区间的问题:
为什么从0−m枚举j,而从1−m枚举i? i不能为0,否则im−j有可能出现负数的情况.
hmmm 其实枚举i,j的区间并不是一定的。
依据: x = i ∗ m − j x=i*m -j x=imj
还能枚举有: i ∈ [ 1 , m ] i\in [1,m] i[1,m] , j ∈ [ 1 , m ] j\in [1,m] j[1,m]
参考资料:BSGS算法 学习笔记

#include
#include
#include
#include
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
ll gcd(ll a,ll b){ return b? gcd(b,a%b):a;}
//const int N=2e5+10;
const ll mod=1e9+7;
using namespace std;
ll read(){
    ll s = 0, f = 1; char ch = getchar();
    while(!isdigit(ch)){
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while(isdigit(ch)) s = (s << 3) + (s << 1) + (ch ^ 48), ch = getchar();
    return s * f;
}
ll a,b,p;
ll qpow(ll x,ll y){
	ll ans=1;
	while(y){
		if(y&1){
			ans=(ans*x)%p;
		}
			x=(x*x)%p;
			y>>=1;
	}
	return ans;
}
ll x;
map<ll,int> mp;
void solve(){
//	cout<
    while(scanf("%lld %lld %lld",&p,&a,&b)!=EOF){
         a%=p;
         if(a==0 and b==0) {
             printf("%d\n",1);
             return ;
         }
         if(a==0)
         {  
         printf("no solution\n");
             return ;
         }
    	 //注意一个小细节,就是在快速幂中是p哦,别写成了mod啦,一个小小的坑~
    	  ll m=ceil(sqrt(p));
    	  mp.clear();
    	  ll ans=b%p;
    	  //枚举区间i:1-m 
    	  for(int i=1;i<=m;i++){
				ans=ans*a%p;
				mp[ans]=i;
//				cout<
		  }
		  ans=1;
		  int flag=0;
		  ll  t=qpow(a,m);
//		  ll top=p/m+1;
		  for(int i=1;i<=m;i++){
			  ans=ans*t%p;
		  	if(mp[ans]){
//		  		cout<<(i*m-mp[ans]+p)%p<
                printf("%lld\n",(i*m-mp[ans]+p)%p);
		  		flag=1;
		  		break;
			  }
		  }
		  if(!flag) printf("no solution\n");
//		   cout<<"no solution"<
	}
}
int main (){
//  freopen("in.txt","r",stdin);
//  freopen("out.txt","w",stdout);
  solve();
  return 0;
}

欧拉定理的推论

最小正整数 x 0 x_0 x0

《算法竞赛进阶指南》数论篇_第8张图片

欧拉的指数循环节

《算法竞赛进阶指南》数论篇_第9张图片
在这里插入图片描述

其他理论

1.在这里插入图片描述 i在区间[x,g(x)]内, ⌊ k / i ⌋ \lfloor k/i \rfloor k/i 的值都相等。

说明

求出i的一段连续区间使得: ⌊ k / i ⌋ \lfloor k/i \rfloor k/i 是个定值。 eg: k=33,i=10; ⌊ 33 / 10 ⌋ \lfloor 33/10 \rfloor 33/10=3; 但是呢? ⌊ 33 / 8 ⌋ \lfloor 33/8 \rfloor 33/8=3; 满足 ⌊ 33 / 9 ⌋ \lfloor 33/9 \rfloor 33/9=3; 满足 ⌊ 33 / 11 ⌋ \lfloor 33/11 \rfloor 33/11=3; 满足 ⌊ 33 / 12 ⌋ \lfloor 33/12 \rfloor 33/12=2; 不满足 所以他的一段连续的区间是:[8,11]。 i在[8,11]内, ⌊ k / i ⌋ \lfloor k/i \rfloor k/i是个定值。

证明
在这里插入图片描述
由于g(x)>=x,所以i在这个区间内是个定值。

来看一到题:余数之和

题意很简单:
《算法竞赛进阶指南》数论篇_第10张图片

这里就用上了该结论。
大概讲一下写代码的思路。
我们知道一个N的正因数个数不超过2* sqrt(N).
(ps:a a ∗ b a*b ab=N 那么asqrt(n) 所以显而易见)
知道了这个就可以说明了 i在[1,N]内 ⌊ N / i ⌋ \lfloor N/i \rfloor N/i 值不同的个数不超过 2 ∗ N 2* \sqrt{N} 2N .
然后就知道了有不超过2* sqrt(N)个的区间。时间复杂度在O( N \sqrt{N} N );
AC代码:

#include
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
ll gcd(ll a,ll b){ return b? gcd(b,a%b):a;}
const int N=2e5+10;
const ll mod=1e9+7;
ll read(){
    ll s = 0, f = 1; char ch = getchar();
    while(!isdigit(ch)){
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while(isdigit(ch)) s = (s << 3) + (s << 1) + (ch ^ 48), ch = getchar();
    return s * f;
}
using namespace std;
ll n,k;
ll sum=0;
void solve(){
    n=read();k=read();
	sum=n*k;
	ll x=1;
	ll y;
	ll cnt;
	while(x<=n){
		if(k/x !=0)
		 y=k/(k/x);
		 else y=n;
		 cnt=y-x+1;
		if(y<=n)
		sum-= (k/x)*cnt*(x+y)/2;
		else {
			sum-=(k/x)*(n-x+1)*(x+n)/2;
		}
		x=y+1;
	}
	cout<< sum<<endl;
}
int main (){
//   freopen("in.txt","r",stdin);
//   freopen("out.txt","w",stdout);
  solve();
//   while(1);
  return 0;
}

参考博客:
同余
Discrete Logging
BSGS算法

你可能感兴趣的:(算法)